diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index bed3d277f45..c0ea058d2dd 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -258,13 +258,13 @@ ko delete -f config/ To look at the controller logs, run: ```shell -kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=tekton-pipelines-controller -o name) +kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=controller -o name) ``` To look at the webhook logs, run: ```shell -kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=tekton-pipelines-webhook -o name) +kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=webhook -o name) ``` To look at the logs for individual `TaskRuns` or `PipelineRuns`, see diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index 495f8f8639f..313907a3bc0 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -18,110 +18,119 @@ package main import ( "context" - "flag" - "log" "os" - apiconfig "github.com/tektoncd/pipeline/pkg/apis/config" + defaultconfig "github.com/tektoncd/pipeline/pkg/apis/config" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" "github.com/tektoncd/pipeline/pkg/contexts" - tklogging "github.com/tektoncd/pipeline/pkg/logging" - "github.com/tektoncd/pipeline/pkg/system" - "go.uber.org/zap" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + "knative.dev/pkg/injection/sharedmain" "knative.dev/pkg/logging" - "knative.dev/pkg/logging/logkey" "knative.dev/pkg/signals" "knative.dev/pkg/webhook" + "knative.dev/pkg/webhook/certificates" + "knative.dev/pkg/webhook/configmaps" + "knative.dev/pkg/webhook/resourcesemantics" + "knative.dev/pkg/webhook/resourcesemantics/defaulting" + "knative.dev/pkg/webhook/resourcesemantics/validation" ) -// WebhookLogKey is the name of the logger for the webhook cmd -const WebhookLogKey = "webhook" +var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{ + v1alpha1.SchemeGroupVersion.WithKind("Pipeline"): &v1alpha1.Pipeline{}, + v1alpha1.SchemeGroupVersion.WithKind("Task"): &v1alpha1.Task{}, + v1alpha1.SchemeGroupVersion.WithKind("ClusterTask"): &v1alpha1.ClusterTask{}, + v1alpha1.SchemeGroupVersion.WithKind("TaskRun"): &v1alpha1.TaskRun{}, + v1alpha1.SchemeGroupVersion.WithKind("PipelineRun"): &v1alpha1.PipelineRun{}, + v1alpha1.SchemeGroupVersion.WithKind("Condition"): &v1alpha1.Condition{}, + v1alpha1.SchemeGroupVersion.WithKind("PipelineResource"): &v1alpha1.PipelineResource{}, +} -func main() { - flag.Parse() - cm, err := configmap.Load("/etc/config-logging") - if err != nil { - log.Fatalf("Error loading logging configuration: %v", err) - } - config, err := logging.NewConfigFromMap(cm) - if err != nil { - log.Fatalf("Error parsing logging configuration: %v", err) - } - logger, atomicLevel := logging.NewLoggerFromConfig(config, WebhookLogKey) - defer func() { - _ = logger.Sync() - }() - logger = logger.With(zap.String(logkey.ControllerType, "webhook")) +func NewDefaultingAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl { + // Decorate contexts with the current state of the config. + store := defaultconfig.NewStore(logging.FromContext(ctx).Named("config-store")) + store.WatchConfigs(cmw) - logger.Info("Starting the Configuration Webhook") + return defaulting.NewAdmissionController(ctx, - // set up signals so we handle the first shutdown signal gracefully - stopCh := signals.SetupSignalHandler() + // Name of the resource webhook. + "webhook.pipeline.tekton.dev", - clusterConfig, err := rest.InClusterConfig() - if err != nil { - logger.Fatal("Failed to get in cluster config", zap.Error(err)) - } + // The path on which to serve the webhook. + "/defaulting", - kubeClient, err := kubernetes.NewForConfig(clusterConfig) - if err != nil { - logger.Fatal("Failed to get the client set", zap.Error(err)) - } - // Watch the logging config map and dynamically update logging levels. - configMapWatcher := configmap.NewInformedWatcher(kubeClient, system.GetNamespace()) - configMapWatcher.Watch(tklogging.ConfigName, logging.UpdateLevelFromConfigMap(logger, atomicLevel, WebhookLogKey)) + // The resources to validate and default. + types, - store := apiconfig.NewStore(logger.Named("config-store")) - store.WatchConfigs(configMapWatcher) + // A function that infuses the context passed to Validate/SetDefaults with custom metadata. + func(ctx context.Context) context.Context { + // FIXME(vdemeester) uncomment that for auto-conversion + // return v1alpha2.WithUpgradeViaDefaulting(store.ToContext(ctx)) + return contexts.WithDefaultConfigurationName(store.ToContext(ctx)) + }, - if err = configMapWatcher.Start(stopCh); err != nil { - logger.Fatalf("failed to start configuration manager: %v", err) - } + // Whether to disallow unknown fields. + true, + ) +} - serviceName := os.Getenv("WEBHOOK_SERVICE_NAME") - if serviceName == "" { - serviceName = "tekton-pipelines-webhook" - } +func NewValidationAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl { + return validation.NewAdmissionController(ctx, - options := webhook.ControllerOptions{ - ServiceName: serviceName, - DeploymentName: serviceName, - Namespace: system.GetNamespace(), - Port: 8443, - SecretName: "webhook-certs", - WebhookName: "webhook.tekton.dev", - ResourceAdmissionControllerPath: "/", - } - resourceHandlers := map[schema.GroupVersionKind]webhook.GenericCRD{ - v1alpha1.SchemeGroupVersion.WithKind("Pipeline"): &v1alpha1.Pipeline{}, - v1alpha1.SchemeGroupVersion.WithKind("Task"): &v1alpha1.Task{}, - v1alpha1.SchemeGroupVersion.WithKind("ClusterTask"): &v1alpha1.ClusterTask{}, - v1alpha1.SchemeGroupVersion.WithKind("TaskRun"): &v1alpha1.TaskRun{}, - v1alpha1.SchemeGroupVersion.WithKind("PipelineRun"): &v1alpha1.PipelineRun{}, - v1alpha1.SchemeGroupVersion.WithKind("Condition"): &v1alpha1.Condition{}, - v1alpha1.SchemeGroupVersion.WithKind("PipelineResource"): &v1alpha1.PipelineResource{}, - } + // Name of the resource webhook. + "validation.webhook.pipeline.tekton.dev", - resourceAdmissionController := webhook.NewResourceAdmissionController(resourceHandlers, options, true) - admissionControllers := map[string]webhook.AdmissionController{ - options.ResourceAdmissionControllerPath: resourceAdmissionController, - } + // The path on which to serve the webhook. + "/resource-validation", - // Decorate contexts with the current state of the config. - ctxFunc := func(ctx context.Context) context.Context { - return contexts.WithDefaultConfigurationName(store.ToContext(ctx)) - } + // The resources to validate and default. + types, - controller, err := webhook.New(kubeClient, options, admissionControllers, logger, ctxFunc) - if err != nil { - logger.Fatal("Error creating admission controller", zap.Error(err)) - } + // A function that infuses the context passed to Validate/SetDefaults with custom metadata. + func(ctx context.Context) context.Context { + return ctx + }, + + // Whether to disallow unknown fields. + true, + ) +} + +func NewConfigValidationController(ctx context.Context, cmw configmap.Watcher) *controller.Impl { + return configmaps.NewAdmissionController(ctx, + + // Name of the configmap webhook. + "config.webhook.pipeline.tekton.dev", - if err := controller.Run(stopCh); err != nil { - logger.Fatal("Error running admission controller", zap.Error(err)) + // The path on which to serve the webhook. + "/config-validation", + + // The configmaps to validate. + configmap.Constructors{ + logging.ConfigMapName(): logging.NewConfigFromConfigMap, + defaultconfig.DefaultsConfigName: defaultconfig.NewDefaultsFromConfigMap, + }, + ) +} + +func main() { + serviceName := os.Getenv("WEBHOOK_SERVICE_NAME") + if serviceName == "" { + serviceName = "webhook" } + + // Set up a signal context with our webhook options + ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{ + ServiceName: serviceName, + Port: 8443, + SecretName: "webhook-certs", + }) + + sharedmain.MainWithContext(ctx, "webhook", + certificates.NewController, + NewDefaultingAdmissionController, + NewValidationAdmissionController, + NewConfigValidationController, + ) } diff --git a/config/200-clusterrole.yaml b/config/200-clusterrole.yaml index 1ca30572693..dec4d991d31 100644 --- a/config/200-clusterrole.yaml +++ b/config/200-clusterrole.yaml @@ -13,7 +13,7 @@ rules: resources: ["deployments/finalizers"] verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] - apiGroups: ["admissionregistration.k8s.io"] - resources: ["mutatingwebhookconfigurations"] + resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"] verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] - apiGroups: ["tekton.dev"] resources: ["tasks", "clustertasks", "taskruns", "pipelines", "pipelineruns", "pipelineresources", "conditions"] diff --git a/config/400-controller-service.yaml b/config/400-controller-service.yaml deleted file mode 100644 index ac86abc3c28..00000000000 --- a/config/400-controller-service.yaml +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2019 Tekton Authors LLC -# -# 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: v1 -kind: Service -metadata: - labels: - app: tekton-pipelines-controller - name: tekton-pipelines-controller - namespace: tekton-pipelines -spec: - ports: - - name: http-metrics - port: 9090 - protocol: TCP - targetPort: 9090 - selector: - app: tekton-pipelines-controller diff --git a/config/400-webhook-service.yaml b/config/400-webhook-service.yaml deleted file mode 100644 index 7d0eddc719e..00000000000 --- a/config/400-webhook-service.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2019 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: v1 -kind: Service -metadata: - labels: - app: tekton-pipelines-webhook - name: tekton-pipelines-webhook - namespace: tekton-pipelines -spec: - ports: - - name: https-webhook - port: 443 - targetPort: 8443 - selector: - app: tekton-pipelines-webhook diff --git a/config/500-webhooks.yaml b/config/500-webhooks.yaml new file mode 100644 index 00000000000..43ca65a263d --- /dev/null +++ b/config/500-webhooks.yaml @@ -0,0 +1,120 @@ +# 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: v1 +kind: Secret +metadata: + name: webhook-certs + namespace: tekton-pipelines + labels: + tekton.pipeline.dev/release: devel +# The data is populated at install time. + +--- +# 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: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +metadata: + name: validation.webhook.pipeline.tekton.dev + labels: + pipeline.tekton.dev/release: devel +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: webhook + namespace: tekton-pipelines + failurePolicy: Fail + sideEffects: None + name: validation.webhook.pipeline.tekton.dev +--- +# 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: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: webhook.pipeline.tekton.dev + labels: + pipeline.tekton.dev/release: devel +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: webhook + namespace: tekton-pipelines + failurePolicy: Fail + sideEffects: None + name: webhook.pipeline.tekton.dev +--- +# 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: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +metadata: + name: config.webhook.pipeline.tekton.dev + labels: + pipeline.tekton.dev/release: devel +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: webhook + namespace: tekton-pipelines + failurePolicy: Fail + sideEffects: None + name: config.webhook.pipeline.tekton.dev + namespaceSelector: + matchExpressions: + - key: pipeline.tekton.dev/release + operator: Exists diff --git a/config/controller.yaml b/config/controller.yaml index 654eae214a0..b7562ecf2f4 100644 --- a/config/controller.yaml +++ b/config/controller.yaml @@ -14,27 +14,27 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: tekton-pipelines-controller + name: controller namespace: tekton-pipelines labels: app.kubernetes.io/name: tekton-pipelines app.kubernetes.io/component: controller - tekton.dev/release: "devel" + pipeline.tekton.dev/release: "devel" spec: replicas: 1 selector: matchLabels: - app: tekton-pipelines-controller + app: controller template: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict: "false" - # tekton.dev/release value replaced with inputs.params.versionTag in pipeline/tekton/publish.yaml - tekton.dev/release: "devel" labels: - app: tekton-pipelines-controller + app: controller app.kubernetes.io/name: tekton-pipelines app.kubernetes.io/component: controller + # tekton.dev/release value replaced with inputs.params.versionTag in pipeline/tekton/publish.yaml + pipeline.tekton.dev/release: "devel" spec: serviceAccountName: tekton-pipelines-controller containers: @@ -74,3 +74,20 @@ spec: - name: config-logging configMap: name: config-logging +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app: controller + pipeline.tekton.dev/release: "devel" + name: controller + namespace: tekton-pipelines +spec: + ports: + - name: http-metrics + port: 9090 + protocol: TCP + targetPort: 9090 + selector: + app: controller diff --git a/config/webhook.yaml b/config/webhook.yaml index 022bb8cf826..71facd582b8 100644 --- a/config/webhook.yaml +++ b/config/webhook.yaml @@ -18,26 +18,28 @@ metadata: # Note: the Deployment name must be the same as the Service name specified in # config/400-webhook-service.yaml. If you change this name, you must also # change the value of WEBHOOK_SERVICE_NAME below. - name: tekton-pipelines-webhook + name: webhook namespace: tekton-pipelines labels: app.kubernetes.io/name: tekton-pipelines app.kubernetes.io/component: webhook-controller - tekton.dev/release: "devel" + pipeline.tekton.dev/release: "devel" spec: replicas: 1 selector: matchLabels: - app: tekton-pipelines-webhook + app: webhook + role: webhook template: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict: "false" - tekton.dev/release: "devel" labels: - app: tekton-pipelines-webhook + app: webhook + role: webhook app.kubernetes.io/name: tekton-pipelines app.kubernetes.io/component: webhook-controller + pipeline.tekton.dev/release: "devel" spec: serviceAccountName: tekton-pipelines-controller containers: @@ -45,17 +47,49 @@ spec: # This is the Go import path for the binary that is containerized # and substituted here. image: github.com/tektoncd/pipeline/cmd/webhook - volumeMounts: - - name: config-logging - mountPath: /etc/config-logging env: - name: SYSTEM_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace + - name: CONFIG_LOGGING_NAME + value: config-logging + - name: CONFIG_OBSERVABILITY_NAME + value: config-observability - name: WEBHOOK_SERVICE_NAME - value: tekton-pipelines-webhook - volumes: - - name: config-logging - configMap: - name: config-logging + value: webhook + - name: METRICS_DOMAIN + value: tekton.dev/pipeline + securityContext: + allowPrivilegeEscalation: false + + ports: + - name: metrics + containerPort: 9090 + - name: profiling + containerPort: 8008 + - name: https-webhook + containerPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + role: webhook + pipeline.tekton.dev/release: devel + name: webhook + namespace: tekton-pipelines +spec: + ports: + # Define metrics and profiling for them to be accessible within service meshes. + - name: http-metrics + port: 9090 + targetPort: 9090 + - name: http-profiling + port: 8008 + targetPort: 8008 + - name: https-webhook + port: 443 + targetPort: 8443 + selector: + role: webhook diff --git a/go.mod b/go.mod index 49b6026e06a..d67316e45af 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/imdario/mergo v0.3.8 // indirect github.com/jenkins-x/go-scm v1.5.65 github.com/json-iterator/go v1.1.8 // indirect + github.com/markbates/inflect v1.0.4 // indirect github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a // indirect github.com/mitchellh/go-homedir v1.1.0 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 // indirect diff --git a/go.sum b/go.sum index f10963b3e8b..befc4a61452 100644 --- a/go.sum +++ b/go.sum @@ -197,6 +197,8 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/envy v1.6.5 h1:X3is06x7v0nW2xiy2yFbbIjwHz57CD6z6MkvqULTCm8= +github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -304,6 +306,8 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= @@ -340,6 +344,8 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/markbates/inflect v1.0.4 h1:5fh1gzTFhfae06u3hzHYO9xe3l3v3nW5Pwt3naLTP5g= +github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs= github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a h1:+J2gw7Bw77w/fbK7wnNJJDKmw1IbWft2Ul5BzrG1Qm8= github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= diff --git a/pkg/apis/pipeline/v1alpha1/types_test.go b/pkg/apis/pipeline/v1alpha1/types_test.go index ebf697c3ca6..85999a4e3b4 100644 --- a/pkg/apis/pipeline/v1alpha1/types_test.go +++ b/pkg/apis/pipeline/v1alpha1/types_test.go @@ -20,15 +20,15 @@ import ( "testing" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" - "knative.dev/pkg/webhook" + "knative.dev/pkg/webhook/resourcesemantics" ) func TestTypes(t *testing.T) { // Assert that types satisfy webhook interface. - var _ webhook.GenericCRD = (*v1alpha1.ClusterTask)(nil) - var _ webhook.GenericCRD = (*v1alpha1.TaskRun)(nil) - var _ webhook.GenericCRD = (*v1alpha1.PipelineResource)(nil) - var _ webhook.GenericCRD = (*v1alpha1.Task)(nil) - var _ webhook.GenericCRD = (*v1alpha1.TaskRun)(nil) - var _ webhook.GenericCRD = (*v1alpha1.Condition)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha1.ClusterTask)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha1.TaskRun)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha1.PipelineResource)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha1.Task)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha1.TaskRun)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha1.Condition)(nil) } diff --git a/pkg/apis/pipeline/v1alpha2/types_test.go b/pkg/apis/pipeline/v1alpha2/types_test.go index ac4346cacce..705c238e779 100644 --- a/pkg/apis/pipeline/v1alpha2/types_test.go +++ b/pkg/apis/pipeline/v1alpha2/types_test.go @@ -20,15 +20,14 @@ import ( "testing" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha2" - "knative.dev/pkg/webhook" + "knative.dev/pkg/webhook/resourcesemantics" ) func TestTypes(t *testing.T) { // Assert that types satisfy webhook interface. - // var _ webhook.GenericCRD = (*v1alpha2.ClusterTask)(nil) - // var _ webhook.GenericCRD = (*v1alpha2.TaskRun)(nil) - // var _ webhook.GenericCRD = (*v1alpha2.PipelineResource)(nil) - var _ webhook.GenericCRD = (*v1alpha2.Task)(nil) - // var _ webhook.GenericCRD = (*v1alpha2.TaskRun)(nil) - // var _ webhook.GenericCRD = (*v1alpha2.Condition)(nil) + // var _ resourcesemantics.GenericCRD = (*v1alpha2.ClusterTask)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha2.TaskRun)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha2.Task)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha2.Pipeline)(nil) + // var _ resourcesemantics.GenericCRD = (*v1alpha2.Condition)(nil) } diff --git a/pkg/apis/pipeline/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/pipeline/v1alpha2/zz_generated.deepcopy.go index 4784a89f386..ad7f2c330b6 100644 --- a/pkg/apis/pipeline/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/pipeline/v1alpha2/zz_generated.deepcopy.go @@ -116,7 +116,7 @@ func (in *ClusterTask) DeepCopyObject() runtime.Object { func (in *ClusterTaskList) DeepCopyInto(out *ClusterTaskList) { *out = *in out.TypeMeta = in.TypeMeta - out.ListMeta = in.ListMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]ClusterTask, len(*in)) diff --git a/pkg/apis/resource/v1alpha1/types_test.go b/pkg/apis/resource/v1alpha1/types_test.go index 05f615069fd..3beb13d0b5a 100644 --- a/pkg/apis/resource/v1alpha1/types_test.go +++ b/pkg/apis/resource/v1alpha1/types_test.go @@ -20,10 +20,10 @@ import ( "testing" "github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1" - "knative.dev/pkg/webhook" + "knative.dev/pkg/webhook/resourcesemantics" ) func TestTypes(t *testing.T) { // Assert that types satisfy webhook interface. - var _ webhook.GenericCRD = (*v1alpha1.PipelineResource)(nil) + var _ resourcesemantics.GenericCRD = (*v1alpha1.PipelineResource)(nil) } diff --git a/pkg/pod/pod.go b/pkg/pod/pod.go index 15511a872bf..49f94979c21 100644 --- a/pkg/pod/pod.go +++ b/pkg/pod/pod.go @@ -38,7 +38,7 @@ const ( // These are effectively const, but Go doesn't have such an annotation. var ( - ReleaseAnnotation = "tekton.dev/release" + ReleaseAnnotation = "pipeline.tekton.dev/release" ReleaseAnnotationValue = version.PipelineVersion groupVersionKind = schema.GroupVersionKind{ diff --git a/pkg/reconciler/pipelinerun/metrics_test.go b/pkg/reconciler/pipelinerun/metrics_test.go index 37050865395..c0b0be6d3dd 100644 --- a/pkg/reconciler/pipelinerun/metrics_test.go +++ b/pkg/reconciler/pipelinerun/metrics_test.go @@ -27,6 +27,9 @@ import ( corev1 "k8s.io/api/core/v1" "knative.dev/pkg/apis" "knative.dev/pkg/metrics/metricstest" + + // Required to setup metrics env for testing + _ "knative.dev/pkg/metrics/testing" rtesting "knative.dev/pkg/reconciler/testing" ) @@ -44,11 +47,12 @@ func TestRecordPipelineRunDurationCount(t *testing.T) { startTime := time.Now() testData := []struct { - name string - taskRun *v1alpha1.PipelineRun - expectedTags map[string]string - expectedDuration float64 - expectedCount int64 + name string + taskRun *v1alpha1.PipelineRun + expectedTags map[string]string + expectedCountTags map[string]string + expectedDuration float64 + expectedCount int64 }{{ name: "for_succeeded_pipeline", taskRun: tb.PipelineRun("pipelinerun-1", "ns", @@ -67,6 +71,9 @@ func TestRecordPipelineRunDurationCount(t *testing.T) { "namespace": "ns", "status": "success", }, + expectedCountTags: map[string]string{ + "status": "success", + }, expectedDuration: 60, expectedCount: 1, }, { @@ -87,6 +94,9 @@ func TestRecordPipelineRunDurationCount(t *testing.T) { "namespace": "ns", "status": "failed", }, + expectedCountTags: map[string]string{ + "status": "failed", + }, expectedDuration: 60, expectedCount: 1, }} @@ -101,7 +111,7 @@ func TestRecordPipelineRunDurationCount(t *testing.T) { err = metrics.DurationAndCount(test.taskRun) assertErrIsNil(err, "DurationAndCount recording recording got an error", t) metricstest.CheckDistributionData(t, "pipelinerun_duration_seconds", test.expectedTags, 1, test.expectedDuration, test.expectedDuration) - metricstest.CheckCountData(t, "pipelinerun_count", test.expectedTags, test.expectedCount) + metricstest.CheckCountData(t, "pipelinerun_count", test.expectedCountTags, test.expectedCount) }) } diff --git a/pkg/reconciler/pipelinerun/pipelinerun_test.go b/pkg/reconciler/pipelinerun/pipelinerun_test.go index a8e392249ed..c25e9c6dd82 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun_test.go +++ b/pkg/reconciler/pipelinerun/pipelinerun_test.go @@ -209,7 +209,7 @@ func TestReconcile(t *testing.T) { t.Log("actions", clients.Pipeline.Actions()) // Check that the PipelineRun was reconciled correctly - reconciledRun, err := clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-success", metav1.GetOptions{}) + reconciledRun, err := clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-success", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting reconciled run out of fake client: %s", err) } @@ -328,7 +328,7 @@ func TestReconcile_PipelineSpecTaskSpec(t *testing.T) { t.Log("actions", clients.Pipeline.Actions()) // Check that the PipelineRun was reconciled correctly - reconciledRun, err := clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-success", metav1.GetOptions{}) + reconciledRun, err := clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-success", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting reconciled run out of fake client: %s", err) } @@ -814,7 +814,7 @@ func TestReconcileOnCompletedPipelineRun(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - reconciledRun, err := clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-completed", metav1.GetOptions{}) + reconciledRun, err := clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-completed", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -878,7 +878,7 @@ func TestReconcileOnCancelledPipelineRun(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - reconciledRun, err := clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-cancelled", metav1.GetOptions{}) + reconciledRun, err := clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-cancelled", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -924,7 +924,7 @@ func TestReconcileWithTimeout(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - reconciledRun, err := clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-with-timeout", metav1.GetOptions{}) + reconciledRun, err := clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-with-timeout", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -978,7 +978,7 @@ func TestReconcileWithoutPVC(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - reconciledRun, err := clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run", metav1.GetOptions{}) + reconciledRun, err := clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting reconciled run out of fake client: %s", err) } @@ -1026,7 +1026,7 @@ func TestReconcileCancelledPipelineRun(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - reconciledRun, err := clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-with-timeout", metav1.GetOptions{}) + reconciledRun, err := clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-with-timeout", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -1094,7 +1094,7 @@ func TestReconcilePropagateLabels(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - _, err = clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-with-labels", metav1.GetOptions{}) + _, err = clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-with-labels", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -1145,7 +1145,7 @@ func TestReconcileWithDifferentServiceAccounts(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - _, err = clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-different-service-accs", metav1.GetOptions{}) + _, err = clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-different-service-accs", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -1181,7 +1181,7 @@ func TestReconcileWithDifferentServiceAccounts(t *testing.T) { } for i := range ps[0].Spec.Tasks { // Check that the expected TaskRun was created - actual, err := clients.Pipeline.Tekton().TaskRuns("foo").Get(taskRunNames[i], metav1.GetOptions{}) + actual, err := clients.Pipeline.TektonV1alpha1().TaskRuns("foo").Get(taskRunNames[i], metav1.GetOptions{}) if err != nil { t.Fatalf("Expected a TaskRun to be created, but it wasn't: %s", err) } @@ -1322,7 +1322,7 @@ func TestReconcilePropagateAnnotations(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - _, err = clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-with-annotations", metav1.GetOptions{}) + _, err = clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-with-annotations", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -1453,7 +1453,7 @@ func TestReconcileWithConditionChecks(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - _, err = clients.Pipeline.Tekton().PipelineRuns("foo").Get(prName, metav1.GetOptions{}) + _, err = clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get(prName, metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } @@ -1566,7 +1566,7 @@ func TestReconcileWithFailingConditionChecks(t *testing.T) { } // Check that the PipelineRun was reconciled correctly - _, err = clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-with-conditions", metav1.GetOptions{}) + _, err = clients.Pipeline.TektonV1alpha1().PipelineRuns("foo").Get("test-pipeline-run-with-conditions", metav1.GetOptions{}) if err != nil { t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err) } diff --git a/pkg/reconciler/taskrun/metrics_test.go b/pkg/reconciler/taskrun/metrics_test.go index 4e00a90eaf1..5a4f5de9b5b 100644 --- a/pkg/reconciler/taskrun/metrics_test.go +++ b/pkg/reconciler/taskrun/metrics_test.go @@ -47,12 +47,13 @@ func TestUninitializedMetrics(t *testing.T) { func TestRecordTaskrunDurationCount(t *testing.T) { startTime := time.Now() - testData := []struct { - name string - taskRun *v1alpha1.TaskRun - expectedTags map[string]string - expectedDuration float64 - expectedCount int64 + for _, c := range []struct { + name string + taskRun *v1alpha1.TaskRun + expectedTags map[string]string + expectedCountTags map[string]string + expectedDuration float64 + expectedCount int64 }{{ name: "for_succeeded_task", taskRun: tb.TaskRun("taskrun-1", "ns", @@ -73,6 +74,9 @@ func TestRecordTaskrunDurationCount(t *testing.T) { "namespace": "ns", "status": "success", }, + expectedCountTags: map[string]string{ + "status": "success", + }, expectedDuration: 60, expectedCount: 1, }, { @@ -95,22 +99,23 @@ func TestRecordTaskrunDurationCount(t *testing.T) { "namespace": "ns", "status": "failed", }, + expectedCountTags: map[string]string{ + "status": "failed", + }, expectedDuration: 60, expectedCount: 1, - }} - - for _, test := range testData { - t.Run(test.name, func(t *testing.T) { + }} { + t.Run(c.name, func(t *testing.T) { unregisterMetrics() metrics, err := NewRecorder() assertErrIsNil(err, "Recorder initialization failed", t) - err = metrics.DurationAndCount(test.taskRun) - assertErrIsNil(err, "DurationAndCount recording got an error", t) - metricstest.CheckDistributionData(t, "taskrun_duration_seconds", test.expectedTags, 1, test.expectedDuration, test.expectedDuration) - metricstest.CheckCountData(t, "taskrun_count", test.expectedTags, test.expectedCount) - + if err := metrics.DurationAndCount(c.taskRun); err != nil { + t.Fatalf("DurationAndCount: %v", err) + } + metricstest.CheckDistributionData(t, "taskrun_duration_seconds", c.expectedTags, 1, c.expectedDuration, c.expectedDuration) + metricstest.CheckCountData(t, "taskrun_count", c.expectedCountTags, c.expectedCount) }) } } @@ -118,12 +123,13 @@ func TestRecordTaskrunDurationCount(t *testing.T) { func TestRecordPipelinerunTaskrunDurationCount(t *testing.T) { startTime := time.Now() - testData := []struct { - name string - taskRun *v1alpha1.TaskRun - expectedTags map[string]string - expectedDuration float64 - expectedCount int64 + for _, c := range []struct { + name string + taskRun *v1alpha1.TaskRun + expectedTags map[string]string + expectedCountTags map[string]string + expectedDuration float64 + expectedCount int64 }{{ name: "for_succeeded_task", taskRun: tb.TaskRun("taskrun-1", "ns", @@ -148,6 +154,9 @@ func TestRecordPipelinerunTaskrunDurationCount(t *testing.T) { "namespace": "ns", "status": "success", }, + expectedCountTags: map[string]string{ + "status": "success", + }, expectedDuration: 60, expectedCount: 1, }, { @@ -174,21 +183,22 @@ func TestRecordPipelinerunTaskrunDurationCount(t *testing.T) { "namespace": "ns", "status": "failed", }, + expectedCountTags: map[string]string{ + "status": "failed", + }, expectedDuration: 60, expectedCount: 1, - }} - - for _, test := range testData { - t.Run(test.name, func(t *testing.T) { + }} { + t.Run(c.name, func(t *testing.T) { unregisterMetrics() metrics, err := NewRecorder() assertErrIsNil(err, "Recorder initialization failed", t) - err = metrics.DurationAndCount(test.taskRun) - assertErrIsNil(err, "DurationAndCount recording got an error", t) - metricstest.CheckDistributionData(t, "pipelinerun_taskrun_duration_seconds", test.expectedTags, 1, test.expectedDuration, test.expectedDuration) - metricstest.CheckCountData(t, "taskrun_count", test.expectedTags, test.expectedCount) - + if err := metrics.DurationAndCount(c.taskRun); err != nil { + t.Fatalf("DurationAndCount: %v", err) + } + metricstest.CheckDistributionData(t, "pipelinerun_taskrun_duration_seconds", c.expectedTags, 1, c.expectedDuration, c.expectedDuration) + metricstest.CheckCountData(t, "taskrun_count", c.expectedCountTags, c.expectedCount) }) } } diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 97ff5977573..f0ee09e39ca 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -57,9 +57,9 @@ function output_pods_logs() { # Called by `fail_test` (provided by `e2e-tests.sh`) to dump info on test failure function dump_extra_cluster_state() { echo ">>> Pipeline controller log:" - kubectl -n tekton-pipelines logs $(get_app_pod tekton-pipelines-controller tekton-pipelines) + kubectl -n tekton-pipelines logs $(get_app_pod controller tekton-pipelines) echo ">>> Pipeline webhook log:" - kubectl -n tekton-pipelines logs $(get_app_pod tekton-pipelines-webhook tekton-pipelines) + kubectl -n tekton-pipelines logs $(get_app_pod webhook tekton-pipelines) } function validate_run() { diff --git a/test/init_test.go b/test/init_test.go index d224d564a4b..089f64a16da 100644 --- a/test/init_test.go +++ b/test/init_test.go @@ -111,9 +111,9 @@ func initializeLogsAndMetrics(t *testing.T) { flag.Set("alsologtostderr", "true") logging.InitializeLogger(knativetest.Flags.LogVerbose) - if knativetest.Flags.EmitMetrics { - logging.InitializeMetricExporter(t.Name()) - } + //if knativetest.Flags.EmitMetrics { + logging.InitializeMetricExporter(t.Name()) + //} }) } diff --git a/vendor/knative.dev/pkg/metrics/testing/config.go b/vendor/knative.dev/pkg/metrics/testing/config.go new file mode 100644 index 00000000000..a0932f005e5 --- /dev/null +++ b/vendor/knative.dev/pkg/metrics/testing/config.go @@ -0,0 +1,27 @@ +/* +Copyright 2019 The Knative 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. +*/ + +package testing + +import ( + "os" + + "knative.dev/pkg/metrics" +) + +func init() { + os.Setenv(metrics.DomainEnv, "knative.dev/testing") +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 65b80ce3291..dceff0a8ab1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -863,6 +863,7 @@ knative.dev/pkg/logging/testing knative.dev/pkg/metrics knative.dev/pkg/metrics/metricskey knative.dev/pkg/metrics/metricstest +knative.dev/pkg/metrics/testing knative.dev/pkg/profiling knative.dev/pkg/ptr knative.dev/pkg/reconciler/testing