From 623eeda9bc7258c93bdc0e660221e888943028ec Mon Sep 17 00:00:00 2001 From: Dibyo Mukherjee Date: Thu, 20 Jun 2019 15:57:05 -0400 Subject: [PATCH] Resolve conditions in pipelinerun reconciler and add them to pr status --- cmd/controller/main.go | 2 + .../pipeline/v1alpha1/pipelinerun_types.go | 12 +++++ .../v1alpha1/pipelinerun/pipelinerun.go | 19 ++++++++ .../resources/conditionresolution.go | 7 +++ .../resources/pipelinerunresolution.go | 46 ++++++++++++++++++- 5 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 pkg/reconciler/v1alpha1/pipelinerun/resources/conditionresolution.go diff --git a/cmd/controller/main.go b/cmd/controller/main.go index 749b72a0650..217a10611f6 100644 --- a/cmd/controller/main.go +++ b/cmd/controller/main.go @@ -113,6 +113,7 @@ func main() { taskRunInformer := pipelineInformerFactory.Tekton().V1alpha1().TaskRuns() resourceInformer := pipelineInformerFactory.Tekton().V1alpha1().PipelineResources() podInformer := kubeInformerFactory.Core().V1().Pods() + conditionInformer := pipelineInformerFactory.Tekton().V1alpha1().Conditions() pipelineInformer := pipelineInformerFactory.Tekton().V1alpha1().Pipelines() pipelineRunInformer := pipelineInformerFactory.Tekton().V1alpha1().PipelineRuns() @@ -134,6 +135,7 @@ func main() { clusterTaskInformer, taskRunInformer, resourceInformer, + conditionInformer, timeoutHandler, ) // Build all of our controllers, with the clients constructed above. diff --git a/pkg/apis/pipeline/v1alpha1/pipelinerun_types.go b/pkg/apis/pipeline/v1alpha1/pipelinerun_types.go index 32a593fd8cb..9c6da75f38f 100644 --- a/pkg/apis/pipeline/v1alpha1/pipelinerun_types.go +++ b/pkg/apis/pipeline/v1alpha1/pipelinerun_types.go @@ -128,6 +128,18 @@ type PipelineRunTaskRunStatus struct { // Status is the TaskRunStatus for the corresponding TaskRun // +optional Status *TaskRunStatus `json:"status,omitempty"` + // ConditionChecks is the Status for the corresponding ConditionCheck + // ConditionChecks are just task runs, so the status is a TaskRunStatus + // +optional + ConditionChecks map[string]*PipelineRunConditionCheckStatus `json:"conditionChecks,omitempty"` +} + +type PipelineRunConditionCheckStatus struct{ + // ConditionName is the name of the Condition + ConditionName string `json:"conditionName,omitempty"` + // Status is the ConditionCheckStatus fpr the corresponding ConditionCheck + // +optional + Status *TaskRunStatus `json:"status,omitempty"` } var pipelineRunCondSet = apis.NewBatchConditionSet() diff --git a/pkg/reconciler/v1alpha1/pipelinerun/pipelinerun.go b/pkg/reconciler/v1alpha1/pipelinerun/pipelinerun.go index 238197bee20..e1437441296 100644 --- a/pkg/reconciler/v1alpha1/pipelinerun/pipelinerun.go +++ b/pkg/reconciler/v1alpha1/pipelinerun/pipelinerun.go @@ -89,6 +89,7 @@ type Reconciler struct { taskLister listers.TaskLister clusterTaskLister listers.ClusterTaskLister resourceLister listers.PipelineResourceLister + conditionLister listers.ConditionLister tracker tracker.Interface configStore configStore timeoutHandler *reconciler.TimeoutSet @@ -106,6 +107,7 @@ func NewController( clusterTaskInformer informers.ClusterTaskInformer, taskRunInformer informers.TaskRunInformer, resourceInformer informers.PipelineResourceInformer, + conditionInformer informers.ConditionInformer, timeoutHandler *reconciler.TimeoutSet, ) *controller.Impl { @@ -117,6 +119,7 @@ func NewController( clusterTaskLister: clusterTaskInformer.Lister(), taskRunLister: taskRunInformer.Lister(), resourceLister: resourceInformer.Lister(), + conditionLister: conditionInformer.Lister(), timeoutHandler: timeoutHandler, } @@ -302,7 +305,11 @@ func (c *Reconciler) reconcile(ctx context.Context, pr *v1alpha1.PipelineRun) er return c.clusterTaskLister.Get(name) }, c.resourceLister.PipelineResources(pr.Namespace).Get, + func(name string) (*v1alpha1.Condition, error) { + return c.conditionLister.Conditions(pr.Namespace).Get(name) + }, p.Spec.Tasks, providedResources, + c.Logger, ) if err != nil { // This Run has failed, so we need to mark it as failed and stop reconciling it @@ -414,6 +421,18 @@ func updateTaskRunsStatus(pr *v1alpha1.PipelineRun, pipelineState []*resources.R prtrs = &v1alpha1.PipelineRunTaskRunStatus{ PipelineTaskName: rprt.PipelineTask.Name, } + if rprt.ConditionChecks != nil { + cStatus := make(map[string]*v1alpha1.PipelineRunConditionCheckStatus) + for n, c := range rprt.ConditionChecks { + cStatus[n] = &v1alpha1.PipelineRunConditionCheckStatus{ + ConditionName: "Coming Soon!", + } + if c != nil { + cStatus[n].Status = &c.Status + } + } + prtrs.ConditionChecks = cStatus + } pr.Status.TaskRuns[rprt.TaskRun.Name] = prtrs } prtrs.Status = &rprt.TaskRun.Status diff --git a/pkg/reconciler/v1alpha1/pipelinerun/resources/conditionresolution.go b/pkg/reconciler/v1alpha1/pipelinerun/resources/conditionresolution.go new file mode 100644 index 00000000000..a85d409393d --- /dev/null +++ b/pkg/reconciler/v1alpha1/pipelinerun/resources/conditionresolution.go @@ -0,0 +1,7 @@ +package resources + +import "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + +// GetCondition is a function used to retrieve PipelineConditions. +type GetCondition func(string) (*v1alpha1.Condition, error) + diff --git a/pkg/reconciler/v1alpha1/pipelinerun/resources/pipelinerunresolution.go b/pkg/reconciler/v1alpha1/pipelinerun/resources/pipelinerunresolution.go index 74dc29271bb..5adf0a66487 100644 --- a/pkg/reconciler/v1alpha1/pipelinerun/resources/pipelinerunresolution.go +++ b/pkg/reconciler/v1alpha1/pipelinerun/resources/pipelinerunresolution.go @@ -57,6 +57,10 @@ type ResolvedPipelineRunTask struct { TaskRun *v1alpha1.TaskRun PipelineTask *v1alpha1.PipelineTask ResolvedTaskResources *resources.ResolvedTaskResources + TaskConditions []*v1alpha1.Condition + // ConditionChecks ~~TaskRuns but for evaling conditions + // TODO: Move this onto a slice of resolvedConditionChecks struct + ConditionChecks map[string]*v1alpha1.TaskRun // Could also be a TaskRun or maybe just a Pod? } // PipelineRunState is a slice of ResolvedPipelineRunTasks the represents the current execution @@ -211,8 +215,10 @@ func ResolvePipelineRun( getTaskRun resources.GetTaskRun, getClusterTask resources.GetClusterTask, getResource resources.GetResource, + getCondition GetCondition, tasks []v1alpha1.PipelineTask, providedResources map[string]v1alpha1.PipelineResourceRef, + logger *zap.SugaredLogger, ) (PipelineRunState, error) { state := []*ResolvedPipelineRunTask{} @@ -224,7 +230,7 @@ func ResolvePipelineRun( TaskRunName: getTaskRunName(pipelineRun.Status.TaskRuns, pt.Name, pipelineRun.Name), } - // Find the Task that this task in the Pipeline this PipelineTask is using + // Find the Task that this PipelineTask is using var t v1alpha1.TaskInterface var err error if pt.TaskRef.Kind == v1alpha1.ClusterTaskKind { @@ -261,12 +267,50 @@ func ResolvePipelineRun( if taskRun != nil { rprt.TaskRun = taskRun } + + // Get all conditions that this pipelineTask will be using, if any + logger.Warnf("!!!!!!! %d", len(pt.Conditions)) + if len(pt.Conditions) > 0 { + rprt.ConditionChecks = make(map[string]*v1alpha1.TaskRun) + logger.Warnf("LENGTH CONDITIONS >0") + for j := range pt.Conditions { + cName := pt.Conditions[j].ConditionRef + c, err := getCondition(cName) + if err != nil { + return nil, xerrors.Errorf("error retrieving Condition %s: %w", cName, err) + } + conditionCheckName := getConditionCheckName(pipelineRun.Status.TaskRuns, rprt.TaskRunName, cName) + conditionCheck, err := getTaskRun(conditionCheckName) + if err != nil { + if !errors.IsNotFound(err) { + return nil, xerrors.Errorf("error retrieving ConditionCheck %s: %w", conditionCheckName, err) + } + } + rprt.TaskConditions = append(rprt.TaskConditions, c) + rprt.ConditionChecks[conditionCheckName] = conditionCheck + } + } + // Add this task to the state of the PipelineRun state = append(state, &rprt) } return state, nil } +// getConditionCheckName should return a unique name for a `ConditionCheck` if one has not already been defined, and the existing one otherwise. +func getConditionCheckName(taskRunStatus map[string]*v1alpha1.PipelineRunTaskRunStatus, trName, conditionName string) string { + trStatus, ok := taskRunStatus[trName] + if ok && trStatus.ConditionChecks != nil { + for k,v := range trStatus.ConditionChecks { + // TODO: Support multiple conditions. We need a name parameter for conditions or use ordering to signify positions + if conditionName == v.ConditionName { + return k + } + } + } + return names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("%s-%s", trName, conditionName)) +} + // getTaskRunName should return a unique name for a `TaskRun` if one has not already been defined, and the existing one otherwise. func getTaskRunName(taskRunsStatus map[string]*v1alpha1.PipelineRunTaskRunStatus, ptName, prName string) string { for k, v := range taskRunsStatus {