diff --git a/config/300-run.yaml b/config/300-run.yaml new file mode 100644 index 00000000000..dda73eaf357 --- /dev/null +++ b/config/300-run.yaml @@ -0,0 +1,71 @@ +# Copyright 2020 The Tekton Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: runs.tekton.dev + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines + pipeline.tekton.dev/release: "devel" + version: "devel" +spec: + group: tekton.dev + preserveUnknownFields: false + validation: + openAPIV3Schema: + type: object + # One can use x-kubernetes-preserve-unknown-fields: true + # at the root of the schema (and inside any properties, additionalProperties) + # to get the traditional CRD behaviour that nothing is pruned, despite + # setting spec.preserveUnknownProperties: false. + # + # See https://kubernetes.io/blog/2019/06/20/crd-structural-schema/ + # See issue: https://github.com/knative/serving/issues/912 + x-kubernetes-preserve-unknown-fields: true + versions: + - name: v1alpha1 + served: true + storage: true + names: + kind: Run + plural: runs + categories: + - tekton + - tekton-pipelines + scope: Namespaced + additionalPrinterColumns: + - name: Succeeded + type: string + JSONPath: ".status.conditions[?(@.type==\"Succeeded\")].status" + - name: Reason + type: string + JSONPath: ".status.conditions[?(@.type==\"Succeeded\")].reason" + - name: StartTime + type: date + JSONPath: .status.startTime + - name: CompletionTime + type: date + JSONPath: .status.completionTime + # Opt into the status subresource so metadata.generation + # starts to increment + subresources: + status: {} + conversion: + strategy: Webhook + webhookClientConfig: + service: + name: tekton-pipelines-webhook + namespace: tekton-pipelines diff --git a/pkg/apis/pipeline/controller.go b/pkg/apis/pipeline/controller.go index 38fe60b4be9..6332e371e4d 100644 --- a/pkg/apis/pipeline/controller.go +++ b/pkg/apis/pipeline/controller.go @@ -21,6 +21,9 @@ const ( // nolint: golint PipelineRunControllerName = "PipelineRun" - // TaskRunControllerName holds the name of the PipelineRun controller + // TaskRunControllerName holds the name of the TaskRun controller TaskRunControllerName = "TaskRun" + + // TaskRunControllerName holds the name of the PipelineRun controller + RunControllerName = "Run" ) diff --git a/pkg/apis/pipeline/register.go b/pkg/apis/pipeline/register.go index c65484d9763..f34e682c67a 100644 --- a/pkg/apis/pipeline/register.go +++ b/pkg/apis/pipeline/register.go @@ -45,6 +45,9 @@ const ( // ConditionNameKey is used as the label identifier for a Condition ConditionNameKey = "/conditionName" + + // RunKey is used as the label identifier for a Run + RunKey = "/run" ) var ( @@ -63,6 +66,11 @@ var ( Group: GroupName, Resource: "taskruns", } + // RunResource represents a Tekton Run + RunResource = schema.GroupResource{ + Group: GroupName, + Resource: "runs", + } // PipelineResource represents a Tekton Pipeline PipelineResource = schema.GroupResource{ Group: GroupName, diff --git a/pkg/apis/pipeline/v1alpha1/register.go b/pkg/apis/pipeline/v1alpha1/register.go index a8d52721405..78b59bfdce1 100644 --- a/pkg/apis/pipeline/v1alpha1/register.go +++ b/pkg/apis/pipeline/v1alpha1/register.go @@ -60,6 +60,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &PipelineRunList{}, &PipelineResource{}, &PipelineResourceList{}, + &Run{}, + &RunList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/pkg/apis/pipeline/v1alpha1/run_defaults.go b/pkg/apis/pipeline/v1alpha1/run_defaults.go new file mode 100644 index 00000000000..9dcd8627147 --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/run_defaults.go @@ -0,0 +1,34 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "context" + + "knative.dev/pkg/apis" +) + +var _ apis.Defaultable = (*Run)(nil) + +func (r *Run) SetDefaults(ctx context.Context) { + ctx = apis.WithinParent(ctx, r.ObjectMeta) + r.Spec.SetDefaults(apis.WithinSpec(ctx)) +} + +func (rs *RunSpec) SetDefaults(ctx context.Context) { + // No defaults to set. +} diff --git a/pkg/apis/pipeline/v1alpha1/run_types.go b/pkg/apis/pipeline/v1alpha1/run_types.go new file mode 100644 index 00000000000..6ada730f44f --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/run_types.go @@ -0,0 +1,196 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "fmt" + "time" + + "github.com/tektoncd/pipeline/pkg/apis/pipeline" + v1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/apis" + duckv1 "knative.dev/pkg/apis/duck/v1" +) + +var ( + runGroupVersionKind = schema.GroupVersionKind{ + Group: SchemeGroupVersion.Group, + Version: SchemeGroupVersion.Version, + Kind: pipeline.RunControllerName, + } +) + +// RunSpec defines the desired state of Run +type RunSpec struct { + // +optional + Ref *TaskRef `json:"ref,omitempty"` + + // +optional + Params []v1beta1.Param `json:"params,omitempty"` + + // TODO(https://github.com/tektoncd/community/pull/128) + // - cancellation + // - timeout + // - inline task spec + // - workspaces ? +} + +// TODO(jasonhall): Move this to a Params type so other code can use it? +func (rs RunSpec) GetParam(name string) *v1beta1.Param { + for _, p := range rs.Params { + if p.Name == name { + return &p + } + } + return nil +} + +type RunStatus struct { + duckv1.Status `json:",inline"` + + // RunStatusFields inlines the status fields. + RunStatusFields `json:",inline"` +} + +var runCondSet = apis.NewBatchConditionSet() + +// GetCondition returns the Condition matching the given type. +func (r *RunStatus) GetCondition(t apis.ConditionType) *apis.Condition { + return runCondSet.Manage(r).GetCondition(t) +} + +// InitializeConditions will set all conditions in runCondSet to unknown for the PipelineRun +// and set the started time to the current time +func (r *RunStatus) InitializeConditions() { + started := false + if r.StartTime.IsZero() { + r.StartTime = &metav1.Time{Time: time.Now()} + started = true + } + conditionManager := runCondSet.Manage(r) + conditionManager.InitializeConditions() + // Ensure the started reason is set for the "Succeeded" condition + if started { + initialCondition := conditionManager.GetCondition(apis.ConditionSucceeded) + initialCondition.Reason = "Started" + conditionManager.SetCondition(*initialCondition) + } +} + +// SetCondition sets the condition, unsetting previous conditions with the same +// type as necessary. +func (r *RunStatus) SetCondition(newCond *apis.Condition) { + if newCond != nil { + runCondSet.Manage(r).SetCondition(*newCond) + } +} + +// GetConditionSet retrieves the condition set for this resource. Implements +// the KRShaped interface. +func (r *Run) GetConditionSet() apis.ConditionSet { return runCondSet } + +// GetStatus retrieves the status of the Parallel. Implements the KRShaped +// interface. +func (r *Run) GetStatus() *duckv1.Status { return &r.Status.Status } + +// RunStatusFields holds the fields of Run's status. This is defined +// separately and inlined so that other types can readily consume these fields +// via duck typing. +type RunStatusFields struct { + // StartTime is the time the build is actually started. + // +optional + StartTime *metav1.Time `json:"startTime,omitempty"` + + // CompletionTime is the time the build completed. + // +optional + CompletionTime *metav1.Time `json:"completionTime,omitempty"` + + // Results reports any output result values to be consumed by later + // tasks in a pipeline. + // +optional + Results []v1beta1.TaskRunResult `json:"results,omitempty"` + + // TODO(jasonhall): Add a field to hold additional arbitrary fields as + // a map[string]interface{}. +} + +// +genclient +// +genreconciler +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Run represents a single execution of a Custom Task. +// +// +k8s:openapi-gen=true +type Run struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +optional + Spec RunSpec `json:"spec,omitempty"` + // +optional + Status RunStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// RunList contains a list of Run +type RunList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + Items []Run `json:"items"` +} + +// GetOwnerReference gets the task run as owner reference for any related objects +func (r *Run) GetOwnerReference() metav1.OwnerReference { + return *metav1.NewControllerRef(r, runGroupVersionKind) +} + +// HasPipelineRunOwnerReference returns true of Run has +// owner reference of type PipelineRun +func (r *Run) HasPipelineRunOwnerReference() bool { + for _, ref := range r.GetOwnerReferences() { + if ref.Kind == pipeline.PipelineRunControllerName { + return true + } + } + return false +} + +// IsDone returns true if the Run's status indicates that it is done. +func (r *Run) IsDone() bool { + return !r.Status.GetCondition(apis.ConditionSucceeded).IsUnknown() +} + +// HasStarted function check whether taskrun has valid start time set in its status +func (r *Run) HasStarted() bool { + return r.Status.StartTime != nil && !r.Status.StartTime.IsZero() +} + +// IsSuccessful returns true if the Run's status indicates that it is done. +func (r *Run) IsSuccessful() bool { + return r.Status.GetCondition(apis.ConditionSucceeded).IsTrue() +} + +// GetRunKey return the taskrun key for timeout handler map +func (r *Run) GetRunKey() string { + // The address of the pointer is a threadsafe unique identifier for the taskrun + return fmt.Sprintf("%s/%p", "Run", r) +} diff --git a/pkg/apis/pipeline/v1alpha1/run_types_test.go b/pkg/apis/pipeline/v1alpha1/run_types_test.go new file mode 100644 index 00000000000..f6cc9a1dbd1 --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/run_types_test.go @@ -0,0 +1,97 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1_test + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + v1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" +) + +func TestGetParams(t *testing.T) { + for _, c := range []struct { + desc string + spec v1alpha1.RunSpec + name string + want *v1beta1.Param + }{{ + desc: "no params", + spec: v1alpha1.RunSpec{}, + name: "anything", + want: nil, + }, { + desc: "found", + spec: v1alpha1.RunSpec{ + Params: []v1beta1.Param{{ + Name: "first", + Value: v1beta1.NewArrayOrString("blah"), + }, { + Name: "foo", + Value: v1beta1.NewArrayOrString("bar"), + }}, + }, + name: "foo", + want: &v1beta1.Param{ + Name: "foo", + Value: v1beta1.NewArrayOrString("bar"), + }, + }, { + desc: "not found", + spec: v1alpha1.RunSpec{ + Params: []v1beta1.Param{{ + Name: "first", + Value: v1beta1.NewArrayOrString("blah"), + }, { + Name: "foo", + Value: v1beta1.NewArrayOrString("bar"), + }}, + }, + name: "bar", + want: nil, + }, { + // This shouldn't happen since it's invalid, but just in + // case, GetParams just returns the first param it finds with + // the specified name. + desc: "multiple with same name", + spec: v1alpha1.RunSpec{ + Params: []v1beta1.Param{{ + Name: "first", + Value: v1beta1.NewArrayOrString("blah"), + }, { + Name: "foo", + Value: v1beta1.NewArrayOrString("bar"), + }, { + Name: "foo", + Value: v1beta1.NewArrayOrString("second bar"), + }}, + }, + name: "foo", + want: &v1beta1.Param{ + Name: "foo", + Value: v1beta1.NewArrayOrString("bar"), + }, + }} { + t.Run(c.desc, func(t *testing.T) { + got := c.spec.GetParam(c.name) + if d := cmp.Diff(c.want, got); d != "" { + t.Fatalf("Diff(-want,+got): %v", d) + } + }) + } +} diff --git a/pkg/apis/pipeline/v1alpha1/run_validation.go b/pkg/apis/pipeline/v1alpha1/run_validation.go new file mode 100644 index 00000000000..5fd50f87af0 --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/run_validation.go @@ -0,0 +1,58 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "context" + + "github.com/tektoncd/pipeline/pkg/apis/validate" + "k8s.io/apimachinery/pkg/api/equality" + "knative.dev/pkg/apis" +) + +var _ apis.Validatable = (*Run)(nil) + +// Validate taskrun +func (r *Run) Validate(ctx context.Context) *apis.FieldError { + if err := validate.ObjectMetadata(r.GetObjectMeta()).ViaField("metadata"); err != nil { + return err + } + return r.Spec.Validate(ctx) +} + +// Validate Run spec +func (rs *RunSpec) Validate(ctx context.Context) *apis.FieldError { + if equality.Semantic.DeepEqual(rs, &RunSpec{}) { + return apis.ErrMissingField("spec") + } + + if rs.Ref == nil { + return apis.ErrMissingField("spec.ref") + } + if rs.Ref.APIVersion == "" { + return apis.ErrMissingField("spec.ref.apiVersion") + } + if rs.Ref.Kind == "" { + return apis.ErrMissingField("spec.ref.kind") + } + + if err := validateParameters("spec.params", rs.Params); err != nil { + return err + } + + return nil +} diff --git a/pkg/apis/pipeline/v1alpha1/run_validation_test.go b/pkg/apis/pipeline/v1alpha1/run_validation_test.go new file mode 100644 index 00000000000..a03151627dc --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/run_validation_test.go @@ -0,0 +1,155 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1_test + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + v1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + "github.com/tektoncd/pipeline/test/diff" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" +) + +func TestRun_Invalid(t *testing.T) { + for _, c := range []struct { + name string + run *v1alpha1.Run + want *apis.FieldError + }{{ + name: "missing spec", + run: &v1alpha1.Run{}, + want: apis.ErrMissingField("spec"), + }, { + name: "invalid metadata", + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{Name: "run.name"}, + }, + want: &apis.FieldError{ + Message: "Invalid resource name: special character . must not be present", + Paths: []string{"metadata.name"}, + }, + }, { + name: "missing ref", + run: &v1alpha1.Run{ + Spec: v1alpha1.RunSpec{ + Ref: nil, + }, + }, + want: apis.ErrMissingField("spec"), + }, { + name: "missing apiVersion", + run: &v1alpha1.Run{ + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: "", + }, + }, + }, + want: apis.ErrMissingField("spec.ref.apiVersion"), + }, { + name: "missing kind", + run: &v1alpha1.Run{ + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: "blah", + Kind: "", + }, + }, + }, + want: apis.ErrMissingField("spec.ref.kind"), + }, { + name: "non-unique params", + run: &v1alpha1.Run{ + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: "blah", + Kind: "blah", + }, + Params: []v1beta1.Param{{ + Name: "foo", + Value: v1beta1.NewArrayOrString("foo"), + }, { + Name: "foo", + Value: v1beta1.NewArrayOrString("foo"), + }}, + }, + }, + want: apis.ErrMultipleOneOf("spec.params"), + }} { + t.Run(c.name, func(t *testing.T) { + err := c.run.Validate(context.Background()) + if d := cmp.Diff(err.Error(), c.want.Error()); d != "" { + t.Error(diff.PrintWantGot(d)) + } + }) + } +} + +func TestRun_Valid(t *testing.T) { + for _, c := range []struct { + name string + run *v1alpha1.Run + }{{ + name: "no params", + run: &v1alpha1.Run{ + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: "blah", + Kind: "blah", + Name: "blah", + }, + }, + }, + }, { + name: "unnamed", + run: &v1alpha1.Run{ + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: "blah", + Kind: "blah", + }, + }, + }, + }, { + name: "unique params", + run: &v1alpha1.Run{ + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: "blah", + Kind: "blah", + }, + Params: []v1beta1.Param{{ + Name: "foo", + Value: v1beta1.NewArrayOrString("foo"), + }, { + Name: "bar", + Value: v1beta1.NewArrayOrString("bar"), + }}, + }, + }, + }} { + t.Run(c.name, func(t *testing.T) { + if err := c.run.Validate(context.Background()); err != nil { + t.Fatalf("validating valid Run: %v", err) + } + }) + } +} diff --git a/pkg/apis/pipeline/v1alpha1/taskrun_validation.go b/pkg/apis/pipeline/v1alpha1/taskrun_validation.go index 7ec21f6e15a..6668d51ea26 100644 --- a/pkg/apis/pipeline/v1alpha1/taskrun_validation.go +++ b/pkg/apis/pipeline/v1alpha1/taskrun_validation.go @@ -84,7 +84,7 @@ func (ts *TaskRunSpec) Validate(ctx context.Context) *apis.FieldError { if err := validateWorkspaceBindings(ctx, ts.Workspaces); err != nil { return err } - if err := validateParameters(ts.Params); err != nil { + if err := validateParameters("spec.inputs.params", ts.Params); err != nil { return err } @@ -102,7 +102,7 @@ func (i TaskRunInputs) Validate(ctx context.Context, path string) *apis.FieldErr if err := validatePipelineResources(ctx, i.Resources, fmt.Sprintf("%s.Resources.Name", path)); err != nil { return err } - return validateParameters(i.Params) + return validateParameters("spec.inputs.params", i.Params) } func (o TaskRunOutputs) Validate(ctx context.Context, path string) *apis.FieldError { @@ -155,12 +155,13 @@ func validatePipelineResources(ctx context.Context, resources []TaskResourceBind return nil } -func validateParameters(params []Param) *apis.FieldError { +// TODO(jasonhall): Share this with v1beta1/taskrun_validation.go +func validateParameters(path string, params []Param) *apis.FieldError { // Template must not duplicate parameter names. seen := sets.NewString() for _, p := range params { if seen.Has(strings.ToLower(p.Name)) { - return apis.ErrMultipleOneOf("spec.inputs.params") + return apis.ErrMultipleOneOf(path) } seen.Insert(p.Name) } diff --git a/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go index 55e61fb5d07..8854c9fe4da 100644 --- a/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go @@ -610,6 +610,142 @@ func (in *PipelineTaskRunSpec) DeepCopy() *PipelineTaskRunSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Run) DeepCopyInto(out *Run) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Run. +func (in *Run) DeepCopy() *Run { + if in == nil { + return nil + } + out := new(Run) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Run) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunList) DeepCopyInto(out *RunList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Run, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunList. +func (in *RunList) DeepCopy() *RunList { + if in == nil { + return nil + } + out := new(RunList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RunList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunSpec) DeepCopyInto(out *RunSpec) { + *out = *in + if in.Ref != nil { + in, out := &in.Ref, &out.Ref + *out = new(v1beta1.TaskRef) + **out = **in + } + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = make([]v1beta1.Param, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunSpec. +func (in *RunSpec) DeepCopy() *RunSpec { + if in == nil { + return nil + } + out := new(RunSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunStatus) DeepCopyInto(out *RunStatus) { + *out = *in + in.Status.DeepCopyInto(&out.Status) + in.RunStatusFields.DeepCopyInto(&out.RunStatusFields) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunStatus. +func (in *RunStatus) DeepCopy() *RunStatus { + if in == nil { + return nil + } + out := new(RunStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RunStatusFields) DeepCopyInto(out *RunStatusFields) { + *out = *in + if in.StartTime != nil { + in, out := &in.StartTime, &out.StartTime + *out = (*in).DeepCopy() + } + if in.CompletionTime != nil { + in, out := &in.CompletionTime, &out.CompletionTime + *out = (*in).DeepCopy() + } + if in.Results != nil { + in, out := &in.Results, &out.Results + *out = make([]v1beta1.TaskRunResult, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunStatusFields. +func (in *RunStatusFields) DeepCopy() *RunStatusFields { + if in == nil { + return nil + } + out := new(RunStatusFields) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Task) DeepCopyInto(out *Task) { *out = *in diff --git a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/fake/fake_pipeline_client.go b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/fake/fake_pipeline_client.go index 5bcbcb1cd5a..f04cb586314 100644 --- a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/fake/fake_pipeline_client.go +++ b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/fake/fake_pipeline_client.go @@ -44,6 +44,10 @@ func (c *FakeTektonV1alpha1) PipelineRuns(namespace string) v1alpha1.PipelineRun return &FakePipelineRuns{c, namespace} } +func (c *FakeTektonV1alpha1) Runs(namespace string) v1alpha1.RunInterface { + return &FakeRuns{c, namespace} +} + func (c *FakeTektonV1alpha1) Tasks(namespace string) v1alpha1.TaskInterface { return &FakeTasks{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/fake/fake_run.go b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/fake/fake_run.go new file mode 100644 index 00000000000..354630d2a96 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/fake/fake_run.go @@ -0,0 +1,140 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeRuns implements RunInterface +type FakeRuns struct { + Fake *FakeTektonV1alpha1 + ns string +} + +var runsResource = schema.GroupVersionResource{Group: "tekton.dev", Version: "v1alpha1", Resource: "runs"} + +var runsKind = schema.GroupVersionKind{Group: "tekton.dev", Version: "v1alpha1", Kind: "Run"} + +// Get takes name of the run, and returns the corresponding run object, and an error if there is any. +func (c *FakeRuns) Get(name string, options v1.GetOptions) (result *v1alpha1.Run, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(runsResource, c.ns, name), &v1alpha1.Run{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Run), err +} + +// List takes label and field selectors, and returns the list of Runs that match those selectors. +func (c *FakeRuns) List(opts v1.ListOptions) (result *v1alpha1.RunList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(runsResource, runsKind, c.ns, opts), &v1alpha1.RunList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.RunList{ListMeta: obj.(*v1alpha1.RunList).ListMeta} + for _, item := range obj.(*v1alpha1.RunList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested runs. +func (c *FakeRuns) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(runsResource, c.ns, opts)) + +} + +// Create takes the representation of a run and creates it. Returns the server's representation of the run, and an error, if there is any. +func (c *FakeRuns) Create(run *v1alpha1.Run) (result *v1alpha1.Run, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(runsResource, c.ns, run), &v1alpha1.Run{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Run), err +} + +// Update takes the representation of a run and updates it. Returns the server's representation of the run, and an error, if there is any. +func (c *FakeRuns) Update(run *v1alpha1.Run) (result *v1alpha1.Run, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(runsResource, c.ns, run), &v1alpha1.Run{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Run), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeRuns) UpdateStatus(run *v1alpha1.Run) (*v1alpha1.Run, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(runsResource, "status", c.ns, run), &v1alpha1.Run{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Run), err +} + +// Delete takes name of the run and deletes it. Returns an error if one occurs. +func (c *FakeRuns) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(runsResource, c.ns, name), &v1alpha1.Run{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeRuns) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(runsResource, c.ns, listOptions) + + _, err := c.Fake.Invokes(action, &v1alpha1.RunList{}) + return err +} + +// Patch applies the patch and returns the patched run. +func (c *FakeRuns) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Run, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(runsResource, c.ns, name, pt, data, subresources...), &v1alpha1.Run{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.Run), err +} diff --git a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/generated_expansion.go index a3b6b03b044..6942df0f45e 100644 --- a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/generated_expansion.go @@ -26,6 +26,8 @@ type PipelineExpansion interface{} type PipelineRunExpansion interface{} +type RunExpansion interface{} + type TaskExpansion interface{} type TaskRunExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/pipeline_client.go b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/pipeline_client.go index f96f3e34db9..5797a3003a7 100644 --- a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/pipeline_client.go +++ b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/pipeline_client.go @@ -30,6 +30,7 @@ type TektonV1alpha1Interface interface { ConditionsGetter PipelinesGetter PipelineRunsGetter + RunsGetter TasksGetter TaskRunsGetter } @@ -55,6 +56,10 @@ func (c *TektonV1alpha1Client) PipelineRuns(namespace string) PipelineRunInterfa return newPipelineRuns(c, namespace) } +func (c *TektonV1alpha1Client) Runs(namespace string) RunInterface { + return newRuns(c, namespace) +} + func (c *TektonV1alpha1Client) Tasks(namespace string) TaskInterface { return newTasks(c, namespace) } diff --git a/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/run.go b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/run.go new file mode 100644 index 00000000000..9efaff0baad --- /dev/null +++ b/pkg/client/clientset/versioned/typed/pipeline/v1alpha1/run.go @@ -0,0 +1,191 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "time" + + v1alpha1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + scheme "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// RunsGetter has a method to return a RunInterface. +// A group's client should implement this interface. +type RunsGetter interface { + Runs(namespace string) RunInterface +} + +// RunInterface has methods to work with Run resources. +type RunInterface interface { + Create(*v1alpha1.Run) (*v1alpha1.Run, error) + Update(*v1alpha1.Run) (*v1alpha1.Run, error) + UpdateStatus(*v1alpha1.Run) (*v1alpha1.Run, error) + Delete(name string, options *v1.DeleteOptions) error + DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error + Get(name string, options v1.GetOptions) (*v1alpha1.Run, error) + List(opts v1.ListOptions) (*v1alpha1.RunList, error) + Watch(opts v1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Run, err error) + RunExpansion +} + +// runs implements RunInterface +type runs struct { + client rest.Interface + ns string +} + +// newRuns returns a Runs +func newRuns(c *TektonV1alpha1Client, namespace string) *runs { + return &runs{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the run, and returns the corresponding run object, and an error if there is any. +func (c *runs) Get(name string, options v1.GetOptions) (result *v1alpha1.Run, err error) { + result = &v1alpha1.Run{} + err = c.client.Get(). + Namespace(c.ns). + Resource("runs"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of Runs that match those selectors. +func (c *runs) List(opts v1.ListOptions) (result *v1alpha1.RunList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.RunList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("runs"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested runs. +func (c *runs) Watch(opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("runs"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a run and creates it. Returns the server's representation of the run, and an error, if there is any. +func (c *runs) Create(run *v1alpha1.Run) (result *v1alpha1.Run, err error) { + result = &v1alpha1.Run{} + err = c.client.Post(). + Namespace(c.ns). + Resource("runs"). + Body(run). + Do(). + Into(result) + return +} + +// Update takes the representation of a run and updates it. Returns the server's representation of the run, and an error, if there is any. +func (c *runs) Update(run *v1alpha1.Run) (result *v1alpha1.Run, err error) { + result = &v1alpha1.Run{} + err = c.client.Put(). + Namespace(c.ns). + Resource("runs"). + Name(run.Name). + Body(run). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *runs) UpdateStatus(run *v1alpha1.Run) (result *v1alpha1.Run, err error) { + result = &v1alpha1.Run{} + err = c.client.Put(). + Namespace(c.ns). + Resource("runs"). + Name(run.Name). + SubResource("status"). + Body(run). + Do(). + Into(result) + return +} + +// Delete takes name of the run and deletes it. Returns an error if one occurs. +func (c *runs) Delete(name string, options *v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("runs"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *runs) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("runs"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched run. +func (c *runs) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Run, err error) { + result = &v1alpha1.Run{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("runs"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index b7c6452058a..3d05774d1c5 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -62,6 +62,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Tekton().V1alpha1().Pipelines().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("pipelineruns"): return &genericInformer{resource: resource.GroupResource(), informer: f.Tekton().V1alpha1().PipelineRuns().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("runs"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Tekton().V1alpha1().Runs().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("tasks"): return &genericInformer{resource: resource.GroupResource(), informer: f.Tekton().V1alpha1().Tasks().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("taskruns"): diff --git a/pkg/client/informers/externalversions/pipeline/v1alpha1/interface.go b/pkg/client/informers/externalversions/pipeline/v1alpha1/interface.go index fa069ae3945..5b9882c30d7 100644 --- a/pkg/client/informers/externalversions/pipeline/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/pipeline/v1alpha1/interface.go @@ -32,6 +32,8 @@ type Interface interface { Pipelines() PipelineInformer // PipelineRuns returns a PipelineRunInformer. PipelineRuns() PipelineRunInformer + // Runs returns a RunInformer. + Runs() RunInformer // Tasks returns a TaskInformer. Tasks() TaskInformer // TaskRuns returns a TaskRunInformer. @@ -69,6 +71,11 @@ func (v *version) PipelineRuns() PipelineRunInformer { return &pipelineRunInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// Runs returns a RunInformer. +func (v *version) Runs() RunInformer { + return &runInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // Tasks returns a TaskInformer. func (v *version) Tasks() TaskInformer { return &taskInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/informers/externalversions/pipeline/v1alpha1/run.go b/pkg/client/informers/externalversions/pipeline/v1alpha1/run.go new file mode 100644 index 00000000000..3fa4984b1b6 --- /dev/null +++ b/pkg/client/informers/externalversions/pipeline/v1alpha1/run.go @@ -0,0 +1,89 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + time "time" + + pipelinev1alpha1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + versioned "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" + internalinterfaces "github.com/tektoncd/pipeline/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/tektoncd/pipeline/pkg/client/listers/pipeline/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// RunInformer provides access to a shared informer and lister for +// Runs. +type RunInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.RunLister +} + +type runInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewRunInformer constructs a new informer for Run type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewRunInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredRunInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredRunInformer constructs a new informer for Run type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredRunInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TektonV1alpha1().Runs(namespace).List(options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TektonV1alpha1().Runs(namespace).Watch(options) + }, + }, + &pipelinev1alpha1.Run{}, + resyncPeriod, + indexers, + ) +} + +func (f *runInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredRunInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *runInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&pipelinev1alpha1.Run{}, f.defaultInformer) +} + +func (f *runInformer) Lister() v1alpha1.RunLister { + return v1alpha1.NewRunLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/injection/informers/pipeline/v1alpha1/run/fake/fake.go b/pkg/client/injection/informers/pipeline/v1alpha1/run/fake/fake.go new file mode 100644 index 00000000000..14d4c6fa1d4 --- /dev/null +++ b/pkg/client/injection/informers/pipeline/v1alpha1/run/fake/fake.go @@ -0,0 +1,40 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package fake + +import ( + context "context" + + fake "github.com/tektoncd/pipeline/pkg/client/injection/informers/factory/fake" + run "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1alpha1/run" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" +) + +var Get = run.Get + +func init() { + injection.Fake.RegisterInformer(withInformer) +} + +func withInformer(ctx context.Context) (context.Context, controller.Informer) { + f := fake.Get(ctx) + inf := f.Tekton().V1alpha1().Runs() + return context.WithValue(ctx, run.Key{}, inf), inf.Informer() +} diff --git a/pkg/client/injection/informers/pipeline/v1alpha1/run/run.go b/pkg/client/injection/informers/pipeline/v1alpha1/run/run.go new file mode 100644 index 00000000000..fc3b89bb9c4 --- /dev/null +++ b/pkg/client/injection/informers/pipeline/v1alpha1/run/run.go @@ -0,0 +1,52 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package run + +import ( + context "context" + + v1alpha1 "github.com/tektoncd/pipeline/pkg/client/informers/externalversions/pipeline/v1alpha1" + factory "github.com/tektoncd/pipeline/pkg/client/injection/informers/factory" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterInformer(withInformer) +} + +// Key is used for associating the Informer inside the context.Context. +type Key struct{} + +func withInformer(ctx context.Context) (context.Context, controller.Informer) { + f := factory.Get(ctx) + inf := f.Tekton().V1alpha1().Runs() + return context.WithValue(ctx, Key{}, inf), inf.Informer() +} + +// Get extracts the typed informer from the context. +func Get(ctx context.Context) v1alpha1.RunInformer { + untyped := ctx.Value(Key{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch github.com/tektoncd/pipeline/pkg/client/informers/externalversions/pipeline/v1alpha1.RunInformer from context.") + } + return untyped.(v1alpha1.RunInformer) +} diff --git a/pkg/client/injection/reconciler/pipeline/v1alpha1/run/controller.go b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/controller.go new file mode 100644 index 00000000000..53d6496a688 --- /dev/null +++ b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/controller.go @@ -0,0 +1,142 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package run + +import ( + context "context" + fmt "fmt" + reflect "reflect" + strings "strings" + + versionedscheme "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/scheme" + client "github.com/tektoncd/pipeline/pkg/client/injection/client" + run "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1alpha1/run" + corev1 "k8s.io/api/core/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + scheme "k8s.io/client-go/kubernetes/scheme" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" + record "k8s.io/client-go/tools/record" + kubeclient "knative.dev/pkg/client/injection/kube/client" + controller "knative.dev/pkg/controller" + logging "knative.dev/pkg/logging" + reconciler "knative.dev/pkg/reconciler" +) + +const ( + defaultControllerAgentName = "run-controller" + defaultFinalizerName = "runs.tekton.dev" +) + +// NewImpl returns a controller.Impl that handles queuing and feeding work from +// the queue through an implementation of controller.Reconciler, delegating to +// the provided Interface and optional Finalizer methods. OptionsFn is used to return +// controller.Options to be used but the internal reconciler. +func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl { + logger := logging.FromContext(ctx) + + // Check the options function input. It should be 0 or 1. + if len(optionsFns) > 1 { + logger.Fatalf("up to one options function is supported, found %d", len(optionsFns)) + } + + runInformer := run.Get(ctx) + + lister := runInformer.Lister() + + rec := &reconcilerImpl{ + LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ + PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { + all, err := lister.List(labels.Everything()) + if err != nil { + return err + } + for _, elt := range all { + // TODO: Consider letting users specify a filter in options. + enq(bkt, types.NamespacedName{ + Namespace: elt.GetNamespace(), + Name: elt.GetName(), + }) + } + return nil + }, + }, + Client: client.Get(ctx), + Lister: lister, + reconciler: r, + finalizerName: defaultFinalizerName, + } + + t := reflect.TypeOf(r).Elem() + queueName := fmt.Sprintf("%s.%s", strings.ReplaceAll(t.PkgPath(), "/", "-"), t.Name()) + + impl := controller.NewImpl(rec, logger, queueName) + agentName := defaultControllerAgentName + + // Pass impl to the options. Save any optional results. + for _, fn := range optionsFns { + opts := fn(impl) + if opts.ConfigStore != nil { + rec.configStore = opts.ConfigStore + } + if opts.FinalizerName != "" { + rec.finalizerName = opts.FinalizerName + } + if opts.AgentName != "" { + agentName = opts.AgentName + } + if opts.SkipStatusUpdates { + rec.skipStatusUpdates = true + } + } + + rec.Recorder = createRecorder(ctx, agentName) + + return impl +} + +func createRecorder(ctx context.Context, agentName string) record.EventRecorder { + logger := logging.FromContext(ctx) + + recorder := controller.GetEventRecorder(ctx) + if recorder == nil { + // Create event broadcaster + logger.Debug("Creating event broadcaster") + eventBroadcaster := record.NewBroadcaster() + watches := []watch.Interface{ + eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof), + eventBroadcaster.StartRecordingToSink( + &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}), + } + recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName}) + go func() { + <-ctx.Done() + for _, w := range watches { + w.Stop() + } + }() + } + + return recorder +} + +func init() { + versionedscheme.AddToScheme(scheme.Scheme) +} diff --git a/pkg/client/injection/reconciler/pipeline/v1alpha1/run/reconciler.go b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/reconciler.go new file mode 100644 index 00000000000..dc6c563c119 --- /dev/null +++ b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/reconciler.go @@ -0,0 +1,440 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package run + +import ( + context "context" + json "encoding/json" + fmt "fmt" + reflect "reflect" + + v1alpha1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + versioned "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" + pipelinev1alpha1 "github.com/tektoncd/pipeline/pkg/client/listers/pipeline/v1alpha1" + zap "go.uber.org/zap" + v1 "k8s.io/api/core/v1" + equality "k8s.io/apimachinery/pkg/api/equality" + errors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + sets "k8s.io/apimachinery/pkg/util/sets" + cache "k8s.io/client-go/tools/cache" + record "k8s.io/client-go/tools/record" + controller "knative.dev/pkg/controller" + logging "knative.dev/pkg/logging" + reconciler "knative.dev/pkg/reconciler" +) + +// Interface defines the strongly typed interfaces to be implemented by a +// controller reconciling v1alpha1.Run. +type Interface interface { + // ReconcileKind implements custom logic to reconcile v1alpha1.Run. Any changes + // to the objects .Status or .Finalizers will be propagated to the stored + // object. It is recommended that implementors do not call any update calls + // for the Kind inside of ReconcileKind, it is the responsibility of the calling + // controller to propagate those properties. The resource passed to ReconcileKind + // will always have an empty deletion timestamp. + ReconcileKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event +} + +// Finalizer defines the strongly typed interfaces to be implemented by a +// controller finalizing v1alpha1.Run. +type Finalizer interface { + // FinalizeKind implements custom logic to finalize v1alpha1.Run. Any changes + // to the objects .Status or .Finalizers will be ignored. Returning a nil or + // Normal type reconciler.Event will allow the finalizer to be deleted on + // the resource. The resource passed to FinalizeKind will always have a set + // deletion timestamp. + FinalizeKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event +} + +// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a +// controller reconciling v1alpha1.Run if they want to process resources for which +// they are not the leader. +type ReadOnlyInterface interface { + // ObserveKind implements logic to observe v1alpha1.Run. + // This method should not write to the API. + ObserveKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event +} + +// ReadOnlyFinalizer defines the strongly typed interfaces to be implemented by a +// controller finalizing v1alpha1.Run if they want to process tombstoned resources +// even when they are not the leader. Due to the nature of how finalizers are handled +// there are no guarantees that this will be called. +type ReadOnlyFinalizer interface { + // ObserveFinalizeKind implements custom logic to observe the final state of v1alpha1.Run. + // This method should not write to the API. + ObserveFinalizeKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event +} + +// reconcilerImpl implements controller.Reconciler for v1alpha1.Run resources. +type reconcilerImpl struct { + // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware + reconciler.LeaderAwareFuncs + + // Client is used to write back status updates. + Client versioned.Interface + + // Listers index properties about resources + Lister pipelinev1alpha1.RunLister + + // Recorder is an event recorder for recording Event resources to the + // Kubernetes API. + Recorder record.EventRecorder + + // configStore allows for decorating a context with config maps. + // +optional + configStore reconciler.ConfigStore + + // reconciler is the implementation of the business logic of the resource. + reconciler Interface + + // finalizerName is the name of the finalizer to reconcile. + finalizerName string + + // skipStatusUpdates configures whether or not this reconciler automatically updates + // the status of the reconciled resource. + skipStatusUpdates bool +} + +// Check that our Reconciler implements controller.Reconciler +var _ controller.Reconciler = (*reconcilerImpl)(nil) + +// Check that our generated Reconciler is always LeaderAware. +var _ reconciler.LeaderAware = (*reconcilerImpl)(nil) + +func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister pipelinev1alpha1.RunLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler { + // Check the options function input. It should be 0 or 1. + if len(options) > 1 { + logger.Fatalf("up to one options struct is supported, found %d", len(options)) + } + + // Fail fast when users inadvertently implement the other LeaderAware interface. + // For the typed reconcilers, Promote shouldn't take any arguments. + if _, ok := r.(reconciler.LeaderAware); ok { + logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r) + } + // TODO: Consider validating when folks implement ReadOnlyFinalizer, but not Finalizer. + + rec := &reconcilerImpl{ + LeaderAwareFuncs: reconciler.LeaderAwareFuncs{ + PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error { + all, err := lister.List(labels.Everything()) + if err != nil { + return err + } + for _, elt := range all { + // TODO: Consider letting users specify a filter in options. + enq(bkt, types.NamespacedName{ + Namespace: elt.GetNamespace(), + Name: elt.GetName(), + }) + } + return nil + }, + }, + Client: client, + Lister: lister, + Recorder: recorder, + reconciler: r, + finalizerName: defaultFinalizerName, + } + + for _, opts := range options { + if opts.ConfigStore != nil { + rec.configStore = opts.ConfigStore + } + if opts.FinalizerName != "" { + rec.finalizerName = opts.FinalizerName + } + } + + return rec +} + +// Reconcile implements controller.Reconciler +func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error { + logger := logging.FromContext(ctx) + + // Convert the namespace/name string into a distinct namespace and name + namespace, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + logger.Errorf("invalid resource key: %s", key) + return nil + } + // Establish whether we are the leader for use below. + isLeader := r.IsLeaderFor(types.NamespacedName{ + Namespace: namespace, + Name: name, + }) + roi, isROI := r.reconciler.(ReadOnlyInterface) + rof, isROF := r.reconciler.(ReadOnlyFinalizer) + if !isLeader && !isROI && !isROF { + // If we are not the leader, and we don't implement either ReadOnly + // interface, then take a fast-path out. + return nil + } + + // If configStore is set, attach the frozen configuration to the context. + if r.configStore != nil { + ctx = r.configStore.ToContext(ctx) + } + + // Add the recorder to context. + ctx = controller.WithEventRecorder(ctx, r.Recorder) + + // Get the resource with this namespace/name. + + getter := r.Lister.Runs(namespace) + + original, err := getter.Get(name) + + if errors.IsNotFound(err) { + // The resource may no longer exist, in which case we stop processing. + logger.Debugf("resource %q no longer exists", key) + return nil + } else if err != nil { + return err + } + + // Don't modify the informers copy. + resource := original.DeepCopy() + + var reconcileEvent reconciler.Event + if resource.GetDeletionTimestamp().IsZero() { + if isLeader { + // Append the target method to the logger. + logger = logger.With(zap.String("targetMethod", "ReconcileKind")) + + // Set and update the finalizer on resource if r.reconciler + // implements Finalizer. + if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil { + return fmt.Errorf("failed to set finalizers: %w", err) + } + + reconciler.PreProcessReconcile(ctx, resource) + + // Reconcile this copy of the resource and then write back any status + // updates regardless of whether the reconciliation errored out. + reconcileEvent = r.reconciler.ReconcileKind(ctx, resource) + + reconciler.PostProcessReconcile(ctx, resource, original) + + } else if isROI { + // Append the target method to the logger. + logger = logger.With(zap.String("targetMethod", "ObserveKind")) + + // Observe any changes to this resource, since we are not the leader. + reconcileEvent = roi.ObserveKind(ctx, resource) + } + } else if fin, ok := r.reconciler.(Finalizer); isLeader && ok { + // Append the target method to the logger. + logger = logger.With(zap.String("targetMethod", "FinalizeKind")) + + // For finalizing reconcilers, if this resource being marked for deletion + // and reconciled cleanly (nil or normal event), remove the finalizer. + reconcileEvent = fin.FinalizeKind(ctx, resource) + if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil { + return fmt.Errorf("failed to clear finalizers: %w", err) + } + } else if !isLeader && isROF { + // Append the target method to the logger. + logger = logger.With(zap.String("targetMethod", "ObserveFinalizeKind")) + + // For finalizing reconcilers, just observe when we aren't the leader. + reconcileEvent = rof.ObserveFinalizeKind(ctx, resource) + } + + if !r.skipStatusUpdates { + // Synchronize the status. + if equality.Semantic.DeepEqual(original.Status, resource.Status) { + // If we didn't change anything then don't call updateStatus. + // This is important because the copy we loaded from the injectionInformer's + // cache may be stale and we don't want to overwrite a prior update + // to status with this stale state. + } else if !isLeader { + logger.Warn("Saw status changes when we aren't the leader!") + // TODO: Consider logging the diff at Debug? + } else if err = r.updateStatus(original, resource); err != nil { + logger.Warnw("Failed to update resource status", zap.Error(err)) + r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed", + "Failed to update status for %q: %v", resource.Name, err) + return err + } + } + + // Report the reconciler event, if any. + if reconcileEvent != nil { + var event *reconciler.ReconcilerEvent + if reconciler.EventAs(reconcileEvent, &event) { + logger.Infow("Returned an event", zap.Any("event", reconcileEvent)) + r.Recorder.Eventf(resource, event.EventType, event.Reason, event.Format, event.Args...) + + // the event was wrapped inside an error, consider the reconciliation as failed + if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent { + return reconcileEvent + } + return nil + } + + logger.Errorw("Returned an error", zap.Error(reconcileEvent)) + r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error()) + return reconcileEvent + } + + return nil +} + +func (r *reconcilerImpl) updateStatus(existing *v1alpha1.Run, desired *v1alpha1.Run) error { + existing = existing.DeepCopy() + return reconciler.RetryUpdateConflicts(func(attempts int) (err error) { + // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API. + if attempts > 0 { + + getter := r.Client.TektonV1alpha1().Runs(desired.Namespace) + + existing, err = getter.Get(desired.Name, metav1.GetOptions{}) + if err != nil { + return err + } + } + + // If there's nothing to update, just return. + if reflect.DeepEqual(existing.Status, desired.Status) { + return nil + } + + existing.Status = desired.Status + + updater := r.Client.TektonV1alpha1().Runs(existing.Namespace) + + _, err = updater.UpdateStatus(existing) + return err + }) +} + +// updateFinalizersFiltered will update the Finalizers of the resource. +// TODO: this method could be generic and sync all finalizers. For now it only +// updates defaultFinalizerName or its override. +func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.Run) (*v1alpha1.Run, error) { + + getter := r.Lister.Runs(resource.Namespace) + + actual, err := getter.Get(resource.Name) + if err != nil { + return resource, err + } + + // Don't modify the informers copy. + existing := actual.DeepCopy() + + var finalizers []string + + // If there's nothing to update, just return. + existingFinalizers := sets.NewString(existing.Finalizers...) + desiredFinalizers := sets.NewString(resource.Finalizers...) + + if desiredFinalizers.Has(r.finalizerName) { + if existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // Add the finalizer. + finalizers = append(existing.Finalizers, r.finalizerName) + } else { + if !existingFinalizers.Has(r.finalizerName) { + // Nothing to do. + return resource, nil + } + // Remove the finalizer. + existingFinalizers.Delete(r.finalizerName) + finalizers = existingFinalizers.List() + } + + mergePatch := map[string]interface{}{ + "metadata": map[string]interface{}{ + "finalizers": finalizers, + "resourceVersion": existing.ResourceVersion, + }, + } + + patch, err := json.Marshal(mergePatch) + if err != nil { + return resource, err + } + + patcher := r.Client.TektonV1alpha1().Runs(resource.Namespace) + + resourceName := resource.Name + resource, err = patcher.Patch(resourceName, types.MergePatchType, patch) + if err != nil { + r.Recorder.Eventf(resource, v1.EventTypeWarning, "FinalizerUpdateFailed", + "Failed to update finalizers for %q: %v", resourceName, err) + } else { + r.Recorder.Eventf(resource, v1.EventTypeNormal, "FinalizerUpdate", + "Updated %q finalizers", resource.GetName()) + } + return resource, err +} + +func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.Run) (*v1alpha1.Run, error) { + if _, ok := r.reconciler.(Finalizer); !ok { + return resource, nil + } + + finalizers := sets.NewString(resource.Finalizers...) + + // If this resource is not being deleted, mark the finalizer. + if resource.GetDeletionTimestamp().IsZero() { + finalizers.Insert(r.finalizerName) + } + + resource.Finalizers = finalizers.List() + + // Synchronize the finalizers filtered by r.finalizerName. + return r.updateFinalizersFiltered(ctx, resource) +} + +func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.Run, reconcileEvent reconciler.Event) (*v1alpha1.Run, error) { + if _, ok := r.reconciler.(Finalizer); !ok { + return resource, nil + } + if resource.GetDeletionTimestamp().IsZero() { + return resource, nil + } + + finalizers := sets.NewString(resource.Finalizers...) + + if reconcileEvent != nil { + var event *reconciler.ReconcilerEvent + if reconciler.EventAs(reconcileEvent, &event) { + if event.EventType == v1.EventTypeNormal { + finalizers.Delete(r.finalizerName) + } + } + } else { + finalizers.Delete(r.finalizerName) + } + + resource.Finalizers = finalizers.List() + + // Synchronize the finalizers filtered by r.finalizerName. + return r.updateFinalizersFiltered(ctx, resource) +} diff --git a/pkg/client/injection/reconciler/pipeline/v1alpha1/run/stub/controller.go b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/stub/controller.go new file mode 100644 index 00000000000..144ec4f89d1 --- /dev/null +++ b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/stub/controller.go @@ -0,0 +1,54 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package run + +import ( + context "context" + + run "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1alpha1/run" + v1alpha1run "github.com/tektoncd/pipeline/pkg/client/injection/reconciler/pipeline/v1alpha1/run" + configmap "knative.dev/pkg/configmap" + controller "knative.dev/pkg/controller" + logging "knative.dev/pkg/logging" +) + +// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT + +// NewController creates a Reconciler for Run and returns the result of NewImpl. +func NewController( + ctx context.Context, + cmw configmap.Watcher, +) *controller.Impl { + logger := logging.FromContext(ctx) + + runInformer := run.Get(ctx) + + // TODO: setup additional informers here. + + r := &Reconciler{} + impl := v1alpha1run.NewImpl(ctx, r) + + logger.Info("Setting up event handlers.") + + runInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue)) + + // TODO: add additional informer event handlers here. + + return impl +} diff --git a/pkg/client/injection/reconciler/pipeline/v1alpha1/run/stub/reconciler.go b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/stub/reconciler.go new file mode 100644 index 00000000000..812b0b770b6 --- /dev/null +++ b/pkg/client/injection/reconciler/pipeline/v1alpha1/run/stub/reconciler.go @@ -0,0 +1,87 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by injection-gen. DO NOT EDIT. + +package run + +import ( + context "context" + + v1alpha1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + run "github.com/tektoncd/pipeline/pkg/client/injection/reconciler/pipeline/v1alpha1/run" + v1 "k8s.io/api/core/v1" + reconciler "knative.dev/pkg/reconciler" +) + +// TODO: PLEASE COPY AND MODIFY THIS FILE AS A STARTING POINT + +// newReconciledNormal makes a new reconciler event with event type Normal, and +// reason RunReconciled. +func newReconciledNormal(namespace, name string) reconciler.Event { + return reconciler.NewEvent(v1.EventTypeNormal, "RunReconciled", "Run reconciled: \"%s/%s\"", namespace, name) +} + +// Reconciler implements controller.Reconciler for Run resources. +type Reconciler struct { + // TODO: add additional requirements here. +} + +// Check that our Reconciler implements Interface +var _ run.Interface = (*Reconciler)(nil) + +// Optionally check that our Reconciler implements Finalizer +//var _ run.Finalizer = (*Reconciler)(nil) + +// Optionally check that our Reconciler implements ReadOnlyInterface +// Implement this to observe resources even when we are not the leader. +//var _ run.ReadOnlyInterface = (*Reconciler)(nil) + +// Optionally check that our Reconciler implements ReadOnlyFinalizer +// Implement this to observe tombstoned resources even when we are not +// the leader (best effort). +//var _ run.ReadOnlyFinalizer = (*Reconciler)(nil) + +// ReconcileKind implements Interface.ReconcileKind. +func (r *Reconciler) ReconcileKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event { + // TODO: use this if the resource implements InitializeConditions. + // o.Status.InitializeConditions() + + // TODO: add custom reconciliation logic here. + + // TODO: use this if the object has .status.ObservedGeneration. + // o.Status.ObservedGeneration = o.Generation + return newReconciledNormal(o.Namespace, o.Name) +} + +// Optionally, use FinalizeKind to add finalizers. FinalizeKind will be called +// when the resource is deleted. +//func (r *Reconciler) FinalizeKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event { +// // TODO: add custom finalization logic here. +// return nil +//} + +// Optionally, use ObserveKind to observe the resource when we are not the leader. +// func (r *Reconciler) ObserveKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event { +// // TODO: add custom observation logic here. +// return nil +// } + +// Optionally, use ObserveFinalizeKind to observe resources being finalized when we are no the leader. +//func (r *Reconciler) ObserveFinalizeKind(ctx context.Context, o *v1alpha1.Run) reconciler.Event { +// // TODO: add custom observation logic here. +// return nil +//} diff --git a/pkg/client/listers/pipeline/v1alpha1/expansion_generated.go b/pkg/client/listers/pipeline/v1alpha1/expansion_generated.go index 9e4b934db74..fc4bd080d6a 100644 --- a/pkg/client/listers/pipeline/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/pipeline/v1alpha1/expansion_generated.go @@ -46,6 +46,14 @@ type PipelineRunListerExpansion interface{} // PipelineRunNamespaceLister. type PipelineRunNamespaceListerExpansion interface{} +// RunListerExpansion allows custom methods to be added to +// RunLister. +type RunListerExpansion interface{} + +// RunNamespaceListerExpansion allows custom methods to be added to +// RunNamespaceLister. +type RunNamespaceListerExpansion interface{} + // TaskListerExpansion allows custom methods to be added to // TaskLister. type TaskListerExpansion interface{} diff --git a/pkg/client/listers/pipeline/v1alpha1/run.go b/pkg/client/listers/pipeline/v1alpha1/run.go new file mode 100644 index 00000000000..194d1a2bf5f --- /dev/null +++ b/pkg/client/listers/pipeline/v1alpha1/run.go @@ -0,0 +1,94 @@ +/* +Copyright 2020 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// RunLister helps list Runs. +type RunLister interface { + // List lists all Runs in the indexer. + List(selector labels.Selector) (ret []*v1alpha1.Run, err error) + // Runs returns an object that can list and get Runs. + Runs(namespace string) RunNamespaceLister + RunListerExpansion +} + +// runLister implements the RunLister interface. +type runLister struct { + indexer cache.Indexer +} + +// NewRunLister returns a new RunLister. +func NewRunLister(indexer cache.Indexer) RunLister { + return &runLister{indexer: indexer} +} + +// List lists all Runs in the indexer. +func (s *runLister) List(selector labels.Selector) (ret []*v1alpha1.Run, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Run)) + }) + return ret, err +} + +// Runs returns an object that can list and get Runs. +func (s *runLister) Runs(namespace string) RunNamespaceLister { + return runNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// RunNamespaceLister helps list and get Runs. +type RunNamespaceLister interface { + // List lists all Runs in the indexer for a given namespace. + List(selector labels.Selector) (ret []*v1alpha1.Run, err error) + // Get retrieves the Run from the indexer for a given namespace and name. + Get(name string) (*v1alpha1.Run, error) + RunNamespaceListerExpansion +} + +// runNamespaceLister implements the RunNamespaceLister +// interface. +type runNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all Runs in the indexer for a given namespace. +func (s runNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Run, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.Run)) + }) + return ret, err +} + +// Get retrieves the Run from the indexer for a given namespace and name. +func (s runNamespaceLister) Get(name string) (*v1alpha1.Run, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("run"), name) + } + return obj.(*v1alpha1.Run), nil +}