From 8f85ec9069fcdfa7dc907806ab3fcabcebaef42f Mon Sep 17 00:00:00 2001 From: Jerop Date: Thu, 26 Aug 2021 01:22:02 -0400 Subject: [PATCH] [cel] CEL Custom Tasks CRD We introduced CEL Custom Tasks to experiment with using an expression language with Tekton Pipelines. Given feedback from the past several months of usage, we have identified three main current challenges: - CEL custom tasks do not take variables for the CEL environment. As such, users cannot evaluate CEL expressions given specific variables or in specific context. For example, as described in https://github.com/tektoncd/experimental/issues/716 and https://github.com/tektoncd/community/issues/403, a user needed to declare runtime storage variables in the CEL environment. - CEL custom tasks are not a CRD thus making them unreusable across different Runs and PipelineRuns. Read more in https://github.com/tektoncd/community/pull/314#pullrequestreview-584219301. - CEL custom tasks take the CEL expressions through Parameters which is misleading to some users. Read more in https://github.com/tektoncd/community/pull/314#pullrequestreview-584219301. To address the above challenges, this change introduces a CRD for CEL Custom Tasks, which takes CEL expressions and CEL environment variables. With this change: - CEL custom tasks now take variables for the CEL environment - CEL custom tasks are reusable across different Runs and PipelineRuns - CEL custom tasks take expressions through its own field Closes https://github.com/tektoncd/community/issues/403 Closes https://github.com/tektoncd/experimental/issues/716 --- cel/.gitignore | 3 - cel/.ko.yaml | 1 + cel/README.md | 354 ++++++++++---- cel/cmd/controller/main.go | 20 +- cel/cmd/webhook/main.go | 131 +++++ cel/config/100-namespace.yaml | 21 - cel/config/200-serviceaccount.yaml | 18 +- cel/config/201-clusterrole.yaml | 86 +++- cel/config/201-role.yaml | 46 +- cel/config/201-rolebinding.yaml | 32 +- cel/config/202-clusterrolebinding.yaml | 84 +++- cel/config/300-cel.yaml | 50 ++ cel/config/400-controller-service.yaml | 41 -- cel/config/500-controller.yaml | 65 ++- cel/config/500-webhook-configuration.yaml | 62 +++ cel/config/500-webhook.yaml | 106 ++++ cel/config/config-logging.yaml | 53 -- ...{celrun-is-red.yaml => celrun-colors.yaml} | 21 +- cel/examples/celrun-get-type.yaml | 17 +- cel/examples/celrun-sevs.yaml | 23 + cel/examples/pipelinerun-celruns.yaml | 46 +- cel/go.mod | 29 +- cel/go.sum | 416 +++++++++------- cel/hack/boilerplate/boilerplate.go.txt | 15 + cel/hack/tools.go | 8 + cel/hack/update-codegen.sh | 47 ++ cel/hack/update-deps.sh | 60 +++ cel/pkg/apis/cel/controller.go | 22 + cel/pkg/apis/cel/register.go | 22 + cel/pkg/apis/cel/v1alpha1/cel_defaults.go | 34 ++ cel/pkg/apis/cel/v1alpha1/cel_types.go | 96 ++++ cel/pkg/apis/cel/v1alpha1/cel_validation.go | 74 +++ .../apis/cel/v1alpha1/cel_validation_test.go | 147 ++++++ cel/pkg/apis/cel/v1alpha1/doc.go | 22 + cel/pkg/apis/cel/v1alpha1/register.go | 54 +++ .../cel/v1alpha1/zz_generated.deepcopy.go | 152 ++++++ .../client/clientset/versioned/clientset.go | 97 ++++ cel/pkg/client/clientset/versioned/doc.go | 20 + .../versioned/fake/clientset_generated.go | 82 ++++ .../client/clientset/versioned/fake/doc.go | 20 + .../clientset/versioned/fake/register.go | 56 +++ .../client/clientset/versioned/scheme/doc.go | 20 + .../clientset/versioned/scheme/register.go | 56 +++ .../versioned/typed/cel/v1alpha1/cel.go | 178 +++++++ .../typed/cel/v1alpha1/cel_client.go | 89 ++++ .../versioned/typed/cel/v1alpha1/doc.go | 20 + .../versioned/typed/cel/v1alpha1/fake/doc.go | 20 + .../typed/cel/v1alpha1/fake/fake_cel.go | 130 +++++ .../cel/v1alpha1/fake/fake_cel_client.go | 40 ++ .../typed/cel/v1alpha1/generated_expansion.go | 21 + .../externalversions/cel/interface.go | 46 ++ .../externalversions/cel/v1alpha1/cel.go | 90 ++++ .../cel/v1alpha1/interface.go | 45 ++ .../informers/externalversions/factory.go | 180 +++++++ .../informers/externalversions/generic.go | 62 +++ .../internalinterfaces/factory_interfaces.go | 40 ++ cel/pkg/client/injection/client/client.go | 57 +++ cel/pkg/client/injection/client/fake/fake.go | 57 +++ .../informers/cel/v1alpha1/cel/cel.go | 52 ++ .../informers/cel/v1alpha1/cel/fake/fake.go | 40 ++ .../cel/v1alpha1/cel/filtered/cel.go | 65 +++ .../cel/v1alpha1/cel/filtered/fake/fake.go | 52 ++ .../injection/informers/factory/factory.go | 56 +++ .../injection/informers/factory/fake/fake.go | 45 ++ .../filtered/fake/fake_filtered_factory.go | 59 +++ .../factory/filtered/filtered_factory.go | 77 +++ cel/pkg/client/listers/cel/v1alpha1/cel.go | 99 ++++ .../cel/v1alpha1/expansion_generated.go | 27 ++ cel/pkg/reconciler/cel/celrun.go | 162 ------- cel/pkg/reconciler/cel/celrun_test.go | 302 ------------ cel/pkg/reconciler/cel/controller.go | 58 --- cel/pkg/reconciler/celrun/celrun.go | 280 +++++++++++ cel/pkg/reconciler/celrun/celrun_test.go | 452 ++++++++++++++++++ cel/pkg/reconciler/celrun/controller.go | 64 +++ cel/test/build_logs.go | 73 +++ cel/test/celrun_test.go | 422 ++++++++++++++++ cel/test/clients.go | 79 +++ cel/test/controller.go | 34 +- cel/test/e2e-cels.sh | 54 +++ cel/test/e2e-common.sh | 66 +++ cel/test/e2e-tests.sh | 43 ++ cel/test/init_test.go | 234 +++++++++ cel/test/wait.go | 64 +++ 83 files changed, 5802 insertions(+), 1061 deletions(-) create mode 100644 cel/.ko.yaml create mode 100644 cel/cmd/webhook/main.go delete mode 100644 cel/config/100-namespace.yaml create mode 100644 cel/config/300-cel.yaml delete mode 100644 cel/config/400-controller-service.yaml create mode 100644 cel/config/500-webhook-configuration.yaml create mode 100644 cel/config/500-webhook.yaml delete mode 100644 cel/config/config-logging.yaml rename cel/examples/{celrun-is-red.yaml => celrun-colors.yaml} (70%) create mode 100644 cel/examples/celrun-sevs.yaml create mode 100644 cel/hack/boilerplate/boilerplate.go.txt create mode 100644 cel/hack/tools.go create mode 100755 cel/hack/update-codegen.sh create mode 100755 cel/hack/update-deps.sh create mode 100644 cel/pkg/apis/cel/controller.go create mode 100644 cel/pkg/apis/cel/register.go create mode 100644 cel/pkg/apis/cel/v1alpha1/cel_defaults.go create mode 100644 cel/pkg/apis/cel/v1alpha1/cel_types.go create mode 100644 cel/pkg/apis/cel/v1alpha1/cel_validation.go create mode 100644 cel/pkg/apis/cel/v1alpha1/cel_validation_test.go create mode 100644 cel/pkg/apis/cel/v1alpha1/doc.go create mode 100644 cel/pkg/apis/cel/v1alpha1/register.go create mode 100644 cel/pkg/apis/cel/v1alpha1/zz_generated.deepcopy.go create mode 100644 cel/pkg/client/clientset/versioned/clientset.go create mode 100644 cel/pkg/client/clientset/versioned/doc.go create mode 100644 cel/pkg/client/clientset/versioned/fake/clientset_generated.go create mode 100644 cel/pkg/client/clientset/versioned/fake/doc.go create mode 100644 cel/pkg/client/clientset/versioned/fake/register.go create mode 100644 cel/pkg/client/clientset/versioned/scheme/doc.go create mode 100644 cel/pkg/client/clientset/versioned/scheme/register.go create mode 100644 cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel.go create mode 100644 cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel_client.go create mode 100644 cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/doc.go create mode 100644 cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/doc.go create mode 100644 cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel.go create mode 100644 cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel_client.go create mode 100644 cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/generated_expansion.go create mode 100644 cel/pkg/client/informers/externalversions/cel/interface.go create mode 100644 cel/pkg/client/informers/externalversions/cel/v1alpha1/cel.go create mode 100644 cel/pkg/client/informers/externalversions/cel/v1alpha1/interface.go create mode 100644 cel/pkg/client/informers/externalversions/factory.go create mode 100644 cel/pkg/client/informers/externalversions/generic.go create mode 100644 cel/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go create mode 100644 cel/pkg/client/injection/client/client.go create mode 100644 cel/pkg/client/injection/client/fake/fake.go create mode 100644 cel/pkg/client/injection/informers/cel/v1alpha1/cel/cel.go create mode 100644 cel/pkg/client/injection/informers/cel/v1alpha1/cel/fake/fake.go create mode 100644 cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/cel.go create mode 100644 cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/fake/fake.go create mode 100644 cel/pkg/client/injection/informers/factory/factory.go create mode 100644 cel/pkg/client/injection/informers/factory/fake/fake.go create mode 100644 cel/pkg/client/injection/informers/factory/filtered/fake/fake_filtered_factory.go create mode 100644 cel/pkg/client/injection/informers/factory/filtered/filtered_factory.go create mode 100644 cel/pkg/client/listers/cel/v1alpha1/cel.go create mode 100644 cel/pkg/client/listers/cel/v1alpha1/expansion_generated.go delete mode 100644 cel/pkg/reconciler/cel/celrun.go delete mode 100644 cel/pkg/reconciler/cel/celrun_test.go delete mode 100644 cel/pkg/reconciler/cel/controller.go create mode 100644 cel/pkg/reconciler/celrun/celrun.go create mode 100644 cel/pkg/reconciler/celrun/celrun_test.go create mode 100644 cel/pkg/reconciler/celrun/controller.go create mode 100644 cel/test/build_logs.go create mode 100644 cel/test/celrun_test.go create mode 100644 cel/test/clients.go create mode 100755 cel/test/e2e-cels.sh create mode 100755 cel/test/e2e-common.sh create mode 100755 cel/test/e2e-tests.sh create mode 100644 cel/test/init_test.go create mode 100644 cel/test/wait.go diff --git a/cel/.gitignore b/cel/.gitignore index 202521131..e99de55b7 100644 --- a/cel/.gitignore +++ b/cel/.gitignore @@ -53,6 +53,3 @@ cmd/*/kodata/source.tar.gz test/pullrequest/pullrequest-init /.bin/ /bin/ - -# allow vendor -!vendor/ diff --git a/cel/.ko.yaml b/cel/.ko.yaml new file mode 100644 index 000000000..6ccd2d5eb --- /dev/null +++ b/cel/.ko.yaml @@ -0,0 +1 @@ +defaultBaseImage: gcr.io/distroless/static:nonroot diff --git a/cel/README.md b/cel/README.md index 590b9cce7..0c5e84559 100644 --- a/cel/README.md +++ b/cel/README.md @@ -5,25 +5,36 @@ This is an experimental project that provides support for Common Expression Language (CEL) in Tekton Pipelines. The functionality is provided by a controller that implements the Custom Task interface. Its use cases include -evaluating complex expressions to be used in [`WhenExpressions`](https://github.com/tektoncd/pipeline/blob/master/docs/pipelines.md#guard-task-execution-using-whenexpressions) -in subsequent `Tasks` to guard their execution. +evaluating complex expressions to be used in [`when` expressions][when-expressions] in subsequent `Tasks` to guard +their execution. + +**Note**: As an experimental project, the syntax and functionality may change at any time. We hope to promote this to a +top level feature with stability guarantees, but we'll gather feedback and re-examine the design before then. - [Install](#install) - [Usage](#usage) + - [Configuring a `CEL`](#configuring-a-cel) + - [Configuring a `CEL` in a `Pipeline`](#configuring-a-cel-in-a-pipeline) + - [Configuring a `CEL` in a `PipelineRun`](#configuring-a-cel-in-a-pipelinerun) + - [Specifying CEL expressions](#specifying-cel-expressions) + - [Specifying CEL environment variables](#specifying-cel-environment-variables) + - [Monitoring execution status](#monitoring-execution-status) + - [Using the evaluation results](#using-the-evaluation-results) - [Uninstall](#uninstall) +- [Contributions](#contributions) ## Install -Install and configure [`ko`](https://github.com/google/ko). +Install and configure [`ko`][ko]. ``` ko apply -f config/ ``` -This will build and install the `CEL Controller` on your cluster, in the namespace `tekton-cel-run`. +This will build and install the `CEL Controller` on your cluster, in the namespace `tekton-pipelines`. ```commandline -$ k get pods -n tekton-cel-run +$ k get pods -n tekton-pipelines NAME READY STATUS RESTARTS AGE cel-controller-654bdc4cc8-7bvvn 1/1 Running 0 3m4s @@ -37,23 +48,40 @@ kubectl apply --filename https://storage.cloud.google.com/tekton-releases-nightl ## Usage -To evaluate a CEL expressions using `Custom Tasks`, we need to define a [`Run`](https://github.com/tektoncd/pipeline/blob/master/docs/runs.md) -type with `apiVersion: cel.tekton.dev/v1alpha1` and `kind: CEL`. The `Run` takes the CEL expressions to be evaluated -as `Parameters`. If executed successfully, the `Run` will produce the evaluation results as `Results` with names corresponding -with the `Parameters` names. See the [examples](examples) folder for `CEL` `Custom Tasks` to run or use as samples. +To evaluate a CEL expressions using `Custom Tasks`, we need to define a [`Run`][run] type with +`apiVersion: custom.tekton.dev/v1alpha1` and `kind: CEL`. + +The `Run` takes the CEL expressions to be evaluated through `expressions` field. The `Run` optionally takes CEL +environment variables through the `variables` field. + +If executed successfully, the `Run` will produce the evaluation results as `Results` with names corresponding +with the `Expressions`'s names. See the [examples](examples) folder for `CELs` to run or use as samples. + +### Configuring a `CEL` -### Configuring a `CEL` `Custom Task` +A `CEL` definition supports the following fields: -The `CEL` `Custom Task` is defined in a `Run`, which supports the following fields: +- Required: + - [`apiVersion`][kubernetes-overview] - Specifies the API version, `custom.tekton.dev/v1alpha1`. + - [`kind`][kubernetes-overview] - Identifies this resource object as a `CEL` object. + - [`metadata`][kubernetes-overview] - Specifies the metadata that uniquely identifies the `CEL`, such as a `name`. + - [`spec`][kubernetes-overview] - Specifies the configuration for the `CEL`. + - [`expressions`](#specifying-cel-expressions) - Specifies the CEL expressions to be evaluated +- Optional: + - [`variables`](#specifying-cel-environment-variables) - Specifies the CEL environment variables -- [`apiVersion`][kubernetes-overview] - Specifies the API version, `tekton.dev/v1alpha1` -- [`kind`][kubernetes-overview] - Identifies this resource object as a `Run` object -- [`metadata`][kubernetes-overview] - Specifies the metadata that uniquely identifies the `Run`, such as a `name` -- [`spec`][kubernetes-overview] - Specifies the configuration for the `Run` -- [`ref`][kubernetes-overview] - Specifies the `CEL` `Custom Task` - - [`apiVersion`][kubernetes-overview] - Specifies the API version, `cel.tekton.dev/v1alpha1` - - [`kind`][kubernetes-overview] - Identifies this resource object as a `CEL` object -- [`params`](#specifying-cel-expressions) - Specifies the CEL expressions to be evaluated as parameters +The example below shows a basic `CEL`: + +```yaml +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-type +spec: + expressions: + - name: expression + value: "type(1)" +``` The example below shows a basic `Run`: @@ -61,207 +89,316 @@ The example below shows a basic `Run`: apiVersion: tekton.dev/v1alpha1 kind: Run metadata: - generateName: celrun- + generateName: get-type- spec: ref: - apiVersion: cel.tekton.dev/v1alpha1 + apiVersion: custom.tekton.dev/v1alpha1 kind: CEL - params: - - name: expression - value: "type(1)" + name: get-type ``` -### Configuring a `CEL` `Custom Task` in a `Pipeline` +### Configuring a `CEL` in a `Pipeline` -The `CEL` `Custom Task` can be specified within a `Pipeline`, as such: +A `CEL` can be specified within a `Pipeline`, as such: ```yaml +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-red +spec: + expressions: + - name: expression + value: "{'blue': '0x000080', 'red': '0xFF0000'}['red']" +--- apiVersion: tekton.dev/v1beta1 kind: Pipeline metadata: - generateName: pipeline- + generateName: pipeline-get-red- spec: tasks: - name: get-red taskRef: - apiVersion: cel.tekton.dev/v1alpha1 + apiVersion: custom.tekton.dev/v1alpha1 kind: CEL - params: - - name: red - value: "{'blue': '0x000080', 'red': '0xFF0000'}['red']" + name: get-red ``` -### Configuring a `CEL` `Custom Task` in a `PipelineRun` +### Configuring a `CEL` in a `PipelineRun` -The `CEL` `Custom Task` can be specified within a `PipelineRun`, as such: +A `CEL` can be specified within a `PipelineRun`, as such: ```yaml +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-blue +spec: + expressions: + - name: expression + value: "{'blue': '0x000080', 'red': '0xFF0000'}['blue']" +--- apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: - generateName: pipelinerun- + generateName: pipelinerun-get-blue- spec: pipelineSpec: tasks: - name: get-blue taskRef: - apiVersion: cel.tekton.dev/v1alpha1 + apiVersion: custom.tekton.dev/v1alpha1 kind: CEL - params: - - name: blue - value: "{'blue': '0x000080', 'red': '0xFF0000'}['blue']" + name: get-blue ``` ### Specifying CEL expressions -The CEL expressions to be evaluated by the `Run` are specified using parameters. The parameters can be specified -in the `Run` directly or be passed through from a `Pipeline` or `PipelineRun`, as such: +The CEL expressions to be evaluated by the `CEL` are specified in `expressions` field, which are made up of `name` and +`value` pairs which are `Strings`. + +```yaml +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-type +spec: + expressions: + - name: type + value: "type(1)" +--- +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + generateName: pipeline-run-get-type- +spec: + serviceAccountName: 'default' + pipelineSpec: + tasks: + - name: get-type + taskRef: + apiVersion: custom.tekton.dev/v1alpha1 + kind: CEL + name: get-type + - name: echo-get-type + when: + - input: "$(tasks.get-type.results.type)" + operator: in + values: ["int"] + taskSpec: + steps: + - name: echo + image: ubuntu + script: echo ISINT! +``` + +For more information about `Parameters`, read [specifying `Parameters`][specifying-parameters]. + +### Specifying CEL environment variables + +For each execution of a `CEL`, we create an evaluation environment. As described in [CEL Evaluation Documentation][cel-evaluation], +context variables can be bound to the environment. + +The CEL variables to be declared in the environment before evaluation by `CEL` are specified in `variables` field, which +are made up of `name` and `value` pairs which are `Strings`. ```yaml +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-sev +spec: + variables: + - name: priority + value: "high" + - name: alert_enable + value: "true" + expressions: + - name: severity + value: "job_priority in ['high', 'normal'] ? 'sev-1' : 'sev-2'" +--- apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: - generateName: pipelinerun- + generateName: pipeline-run-get-sev- spec: + serviceAccountName: 'default' pipelineSpec: - params: - - name: is-red-expr - type: string tasks: - - name: is-red + - name: get-sev taskRef: - apiVersion: cel.tekton.dev/v1alpha1 + apiVersion: custom.tekton.dev/v1alpha1 kind: CEL - params: - - name: is-red-expr - value: "$(params.is-red-expr)" - params: - - name: is-red-expr - value: "{'blue': '0x000080', 'red': '0xFF0000'}['red'] == '0xFF0000'" + name: get-sev + - name: is-severe + when: + - input: "$(tasks.get-sev.results.severity)" + operator: in + values: ["true"] + taskSpec: + steps: + - name: echo + image: ubuntu + script: echo SEVERE! ``` -For more information about specifying `Parameters`, read [specifying parameters](https://github.com/tektoncd/pipeline/blob/master/docs/pipelines.md#specifying-parameters). +For more information about `Parameters`, read [specifying `Parameters`][specifying-parameters]. For more information +about CEL environment, read [environment setup][cel-docs]. ### Monitoring execution status As the `Run` executes, its `status` field accumulates information about the execution status of the `Run` in general. If the evaluation is successful, it will also contain the `Results` of the evaluation under `status.results` with the -corresponding names of the CEL expressions as provided in the `Parameters`. +corresponding names of the CEL expressions as provided in the `expressions`. ```yaml -Name: celrun-is-red-8lbwv +Name: colors-xgtb9 Namespace: default +Labels: custom.tekton.dev/cel=colors +Annotations: API Version: tekton.dev/v1alpha1 Kind: Run Metadata: - Creation Timestamp: 2021-01-20T17:51:52Z - Generate Name: celrun-is-red- + Creation Timestamp: 2021-08-26T05:03:24Z + Generate Name: colors- # […] Spec: - Params: - Name: red - Value: {'blue': '0x000080', 'red': '0xFF0000'}['red'] - Name: is-red - Value: {'blue': '0x000080', 'red': '0xFF0000'}['red'] == '0xFF0000' Ref: - API Version: cel.tekton.dev/v1alpha1 + API Version: custom.tekton.dev/v1alpha1 Kind: CEL + Name: colors Service Account Name: default Status: - Completion Time: 2021-01-20T17:51:52Z + Completion Time: 2021-08-26T05:03:24Z Conditions: - Last Transition Time: 2021-01-20T17:51:52Z + Last Transition Time: 2021-08-26T05:03:24Z Message: CEL expressions were evaluated successfully Reason: EvaluationSuccess Status: True Type: Succeeded - Extra Fields: - Observed Generation: 1 + Extra Fields: + Results: + Name: red + Value: 0xFF0000 + Name: blue + Value: 0x000080 + Name: is-red + Value: true + Name: is-blue + Value: false + Spec: + Expressions: + Name: red + Value: {'blue': '0x000080', 'red': '0xFF0000'}['red'] + Name: blue + Value: {'blue': '0x000080', 'red': '0xFF0000'}['blue'] + Name: is-red + Value: {'blue': '0x000080', 'red': '0xFF0000'}['red'] == '0xFF0000' + Name: is-blue + Value: {'blue': '0x000080', 'red': '0xFF0000'}['blue'] == '0xFF0000' + Observed Generation: 1 Results: Name: red Value: 0xFF0000 + Name: blue + Value: 0x000080 Name: is-red Value: true - Start Time: 2021-01-20T17:51:52Z + Name: is-blue + Value: false + Start Time: 2021-08-26T05:03:24Z Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal RunReconciled 13s cel-controller Run reconciled: "default/celrun-is-red-8lbwv" + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Started 18s (x2 over 18s) CEL + Normal Succeeded 18s (x2 over 18s) CEL CEL expressions were evaluated successfully ``` -If no CEL expressions are provided, any CEL expression is invalid or there's any other error, the `CEL` `Custom Task` -will fail and the details will be included in `status.conditions` as such: +If no CEL expressions are provided, any CEL expression is invalid or there's any other error, the `Run` will fail and +the details will be included in `status.conditions` as such: ```yaml -Name: celrun-is-red-4ttr8 +Name: colors-f8n9t Namespace: default +Labels: custom.tekton.dev/cel=colors +Annotations: API Version: tekton.dev/v1alpha1 Kind: Run Metadata: - Creation Timestamp: 2021-01-20T17:58:53Z - Generate Name: celrun-is-red- + Creation Timestamp: 2021-08-26T05:06:34Z + Generate Name: colors- # […] Spec: Ref: - API Version: cel.tekton.dev/v1alpha1 + API Version: custom.tekton.dev/v1alpha1 Kind: CEL + Name: colors Service Account Name: default Status: - Completion Time: 2021-01-20T17:58:53Z + Completion Time: 2021-08-26T05:06:34Z Conditions: - Last Transition Time: 2021-01-20T17:58:53Z - Message: Run can't be run because it has an invalid spec - missing field(s) params + Last Transition Time: 2021-08-26T05:06:34Z + Message: Run can't be run because it has an invalid spec - missing field(s): expressions Reason: RunValidationFailed Status: False Type: Succeeded - Extra Fields: - Observed Generation: 1 - Start Time: 2021-01-20T17:58:53Z -Events: + Extra Fields: + Spec: + Expressions: + Observed Generation: 1 + Start Time: 2021-08-26T05:06:34Z +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Started 14s CEL + Warning Failed 14s CEL Run can't be run because it has an invalid spec - missing field(s): expressions ``` -For more information about monitoring `Run` in general, read [monitoring execution status](https://github.com/tektoncd/pipeline/blob/master/docs/runs.md#monitoring-execution-status). +For general information about monitoring a `Run`, read [monitoring execution status][monitoring-run-execution-status]. ### Using the evaluation results A successful `Run` contains the `Results` of evaluating the CEL expressions under `status.results`, with the name of -each evaluation `Result` matching the name of the corresponding CEL expression as provided in the `Parameters`. +each evaluation `Result` matching the name of the corresponding CEL expression as provided in `expressions`. + Users can reference the `Results` in subsequent `Tasks` using variable substitution, as such: ```yaml +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-type +spec: + expressions: + - name: type + value: "type(1)" +--- apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: - generateName: pipelinerun- + generateName: pipeline-run-get-type- spec: + serviceAccountName: 'default' pipelineSpec: - params: - - name: is-red-expr - type: string tasks: - - name: is-red + - name: get-type taskRef: - apiVersion: cel.tekton.dev/v1alpha1 + apiVersion: custom.tekton.dev/v1alpha1 kind: CEL - params: - - name: is-red-expr - value: "$(params.is-red-expr)" - - name: echo-is-red + name: get-type + - name: echo-get-type when: - - input: "$(tasks.is-red.results.is-red-expr)" + - input: "$(tasks.get-type.results.type)" operator: in - values: ["true"] + values: ["int"] taskSpec: steps: - name: echo image: ubuntu - script: echo RED! - params: - - name: is-red-expr - value: "{'blue': '0x000080', 'red': '0xFF0000'}['red'] == '0xFF0000'" + script: echo ISINT! ``` -For more information about using `Results`, read [using results](https://github.com/tektoncd/pipeline/blob/master/docs/pipelines.md#using-results). +For more information about using `Results`, read [using results][using-results]. ## Uninstall @@ -276,5 +413,12 @@ This will delete the `CEL Controller` and related resources on your cluster. Read an overview of our processes in [Tekton Community](https://github.com/tektoncd/community). -[kubernetes-overview]: -https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields +[ko]: https://github.com/google/ko +[run]: https://github.com/tektoncd/pipeline/blob/main/docs/runs.md +[kubernetes-overview]: https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields +[when-expressions]: https://github.com/tektoncd/pipeline/blob/main/docs/pipelines.md#guard-task-execution-using-when-expressions +[specifying-parameters]: https://github.com/tektoncd/pipeline/blob/master/docs/pipelines.md#specifying-parameters +[monitoring-run-execution-status]: https://github.com/tektoncd/pipeline/blob/main/docs/runs.md#monitoring-execution-status +[using-results]: https://github.com/tektoncd/pipeline/blob/main/docs/pipelines.md#using-results +[cel-docs]: https://github.com/google/cel-go#environment-setup +[cel-evaluation]: https://github.com/google/cel-spec/blob/master/doc/langdef.md#evaluation \ No newline at end of file diff --git a/cel/cmd/controller/main.go b/cel/cmd/controller/main.go index 55389b588..e99809cac 100644 --- a/cel/cmd/controller/main.go +++ b/cel/cmd/controller/main.go @@ -17,10 +17,26 @@ limitations under the License. package main import ( - "github.com/tektoncd/experimental/cel/pkg/reconciler/cel" + "flag" + "github.com/tektoncd/experimental/cel/pkg/reconciler/celrun" + corev1 "k8s.io/api/core/v1" + "knative.dev/pkg/injection" "knative.dev/pkg/injection/sharedmain" + "knative.dev/pkg/signals" +) + +const ( + // ControllerLogKey is the name of the logger for the controller cmd + ControllerLogKey = "tekton-cel-controller" +) + +var ( + namespace = flag.String("namespace", corev1.NamespaceAll, "Namespace to restrict informer to. Optional, defaults to all namespaces.") ) func main() { - sharedmain.Main(cel.ControllerName, cel.NewController) + flag.Parse() + sharedmain.MainWithContext(injection.WithNamespaceScope(signals.NewContext(), *namespace), ControllerLogKey, + celrun.NewController(*namespace), + ) } diff --git a/cel/cmd/webhook/main.go b/cel/cmd/webhook/main.go new file mode 100644 index 000000000..18988b99a --- /dev/null +++ b/cel/cmd/webhook/main.go @@ -0,0 +1,131 @@ +/* +Copyright 2021 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 main + +import ( + "context" + "github.com/tektoncd/experimental/cel/pkg/apis/cel" + "knative.dev/pkg/injection/sharedmain" + "os" + + celv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + defaultconfig "github.com/tektoncd/pipeline/pkg/apis/config" + "github.com/tektoncd/pipeline/pkg/contexts" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" + "knative.dev/pkg/injection" + "knative.dev/pkg/system" + + "knative.dev/pkg/logging" + "knative.dev/pkg/signals" + "knative.dev/pkg/webhook" + "knative.dev/pkg/webhook/certificates" + "knative.dev/pkg/webhook/resourcesemantics" + "knative.dev/pkg/webhook/resourcesemantics/defaulting" + "knative.dev/pkg/webhook/resourcesemantics/validation" +) + +const ( + // WebhookLogKey is the name of the logger for the webhook cmd. + // This name is also used to form lease names for the leader election of the webhook's controllers. + WebhookLogKey = "tekton-cel-webhook" +) + +var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{ + celv1alpha1.SchemeGroupVersion.WithKind(cel.ControllerName): &celv1alpha1.CEL{}, +} + +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) + + return defaulting.NewAdmissionController(ctx, + + // Name of the resource webhook. + "webhook.cel.custom.tekton.dev", + + // The path on which to serve the webhook. + "/defaulting", + + // The resources to validate and default. + types, + + // A function that infuses the context passed to Validate/SetDefaults with custom metadata. + func(ctx context.Context) context.Context { + return contexts.WithUpgradeViaDefaulting(store.ToContext(ctx)) + }, + + // Whether to disallow unknown fields. + true, + ) +} + +func newValidationAdmissionController(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) + return validation.NewAdmissionController(ctx, + + // Name of the resource webhook. + "validation.webhook.cel.custom.tekton.dev", + + // The path on which to serve the webhook. + "/resource-validation", + + // The resources to validate and default. + types, + + // A function that infuses the context passed to Validate/SetDefaults with custom metadata. + func(ctx context.Context) context.Context { + return contexts.WithUpgradeViaDefaulting(store.ToContext(ctx)) + }, + + // Whether to disallow unknown fields. + true, + ) +} + +func main() { + serviceName := os.Getenv("WEBHOOK_SERVICE_NAME") + if serviceName == "" { + serviceName = "tekton-cel-webhook" + } + + secretName := os.Getenv("WEBHOOK_SECRET_NAME") + if secretName == "" { + secretName = "tekton-cel-webhook-certs" // #nosec + } + + // Scope informers to the webhook's namespace instead of cluster-wide + ctx := injection.WithNamespaceScope(signals.NewContext(), system.Namespace()) + + // Set up a signal context with our webhook options + ctx = webhook.WithOptions(ctx, webhook.Options{ + ServiceName: serviceName, + Port: 8443, + SecretName: secretName, + }) + + sharedmain.WebhookMainWithConfig(ctx, WebhookLogKey, + sharedmain.ParseAndGetConfigOrDie(), + certificates.NewController, + newDefaultingAdmissionController, + newValidationAdmissionController, + ) +} diff --git a/cel/config/100-namespace.yaml b/cel/config/100-namespace.yaml deleted file mode 100644 index b6fd2b8d0..000000000 --- a/cel/config/100-namespace.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2021 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: Namespace -metadata: - name: tekton-cel-run - labels: - app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run diff --git a/cel/config/200-serviceaccount.yaml b/cel/config/200-serviceaccount.yaml index dad3c3f61..9b1c11e0e 100644 --- a/cel/config/200-serviceaccount.yaml +++ b/cel/config/200-serviceaccount.yaml @@ -15,9 +15,19 @@ apiVersion: v1 kind: ServiceAccount metadata: - name: cel-controller - namespace: tekton-cel-run + name: tekton-cel-controller + namespace: tekton-pipelines labels: - app.kubernetes.io/component: cel-controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run + app.kubernetes.io/part-of: tekton-cel +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tekton-cel-webhook + namespace: tekton-pipelines + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel diff --git a/cel/config/201-clusterrole.yaml b/cel/config/201-clusterrole.yaml index 407e7f7da..1b93af007 100644 --- a/cel/config/201-clusterrole.yaml +++ b/cel/config/201-clusterrole.yaml @@ -15,29 +15,89 @@ kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: cel-controller-cluster-access + name: tekton-cel-controller-cluster-access labels: - app.kubernetes.io/component: cel-controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run + app.kubernetes.io/part-of: tekton-cel rules: - # Controller needs cluster access to all Run CRs. + # Controller needs cluster access to all of the CRDs that it is responsible for managing. - apiGroups: ["tekton.dev"] resources: ["runs"] verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] - - apiGroups: ["tekton.dev"] - resources: ["runs/finalizers"] - verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] - apiGroups: ["tekton.dev"] resources: ["runs/status"] verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] - - # Controller needs cluster access to leases for leader election. - - apiGroups: ["coordination.k8s.io"] - resources: ["leases"] + - apiGroups: ["custom.tekton.dev"] + resources: ["cels"] verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] - - # Controller needs permission to emit events associated with Run CRs. +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + # This is the access that the controller needs on a per-namespace basis. + name: tekton-cel-controller-tenant-access + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +rules: - apiGroups: [""] resources: ["events"] verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-cel-webhook-cluster-access + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +rules: + # The webhook needs to be able to list and update customresourcedefinitions, + # mainly to update the webhook certificates. + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions", "customresourcedefinitions/status"] + resourceNames: ["webhook.cel.custom.tekton.dev"] + verbs: ["get", "list", "update", "patch", "watch"] + - apiGroups: ["admissionregistration.k8s.io"] + # The webhook performs a reconciliation on these two resources and continuously + # updates configuration. + resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"] + # knative starts informers on these things, which is why we need get, list and watch. + resourceNames: ["webhook.cel.custom.tekton.dev"] + verbs: ["list", "watch"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + # This mutating webhook is responsible for applying defaults to tekton objects + # as they are received. + resourceNames: ["webhook.cel.custom.tekton.dev"] + # When there are changes to the configs or secrets, knative updates the mutatingwebhook config + # with the updated certificates or the refreshed set of rules. + verbs: ["get", "update"] + - apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + # validation.webhook.cel.custom.tekton.dev performs schema validation when you, for example, create cels. + resourceNames: ["validation.webhook.cel.custom.tekton.dev"] + # When there are changes to the configs or secrets, knative updates the validatingwebhook config + # with the updated certificates or the refreshed set of rules. + verbs: ["get", "update"] + - apiGroups: ["policy"] + resources: ["podsecuritypolicies"] + resourceNames: ["tekton-pipelines"] + verbs: ["use"] +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-cel-leader-election + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +rules: + # We uses leases for leaderelection + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + resourceNames: ["cel.custom.tekton.dev"] + verbs: ["get", "list", "create", "update", "delete", "patch", "watch"] diff --git a/cel/config/201-role.yaml b/cel/config/201-role.yaml index 4f6ee32ee..076ff473b 100644 --- a/cel/config/201-role.yaml +++ b/cel/config/201-role.yaml @@ -15,18 +15,54 @@ kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: - name: cel-controller - namespace: tekton-cel-run + name: tekton-cel-controller + namespace: tekton-pipelines labels: - app.kubernetes.io/component: cel-controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run + app.kubernetes.io/part-of: tekton-cel rules: - apiGroups: [""] resources: ["configmaps"] verbs: ["list", "watch"] - # The controller needs access to these configmaps for logging information and runtime configuration. - apiGroups: [""] resources: ["configmaps"] verbs: ["get"] resourceNames: ["config-logging", "config-observability", "config-leader-election"] + - apiGroups: ["policy"] + resources: ["podsecuritypolicies"] + resourceNames: ["tekton-pipelines"] + verbs: ["use"] +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-cel-webhook + namespace: tekton-pipelines + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +rules: + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["list", "watch"] + # The webhook needs access to these configmaps for logging information. + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get"] + resourceNames: ["config-logging", "config-observability", "config-leader-election"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["list", "watch"] + # The webhook daemon makes a reconciliation loop on tekton-cel-webhook-certs. Whenever + # the secret changes it updates the webhook configurations with the certificates + # stored in the secret. + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "update"] + resourceNames: ["tekton-cel-webhook-certs"] + - apiGroups: ["policy"] + resources: ["podsecuritypolicies"] + resourceNames: ["tekton-pipelines"] + verbs: ["use"] diff --git a/cel/config/201-rolebinding.yaml b/cel/config/201-rolebinding.yaml index 25c37d9d3..4b10cf5fc 100644 --- a/cel/config/201-rolebinding.yaml +++ b/cel/config/201-rolebinding.yaml @@ -15,17 +15,35 @@ apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: - name: cel-controller - namespace: tekton-cel-run + name: tekton-cel-controller + namespace: tekton-pipelines labels: - app.kubernetes.io/component: cel-controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run + app.kubernetes.io/part-of: tekton-cel subjects: - kind: ServiceAccount - name: cel-controller - namespace: tekton-cel-run + name: tekton-cel-controller + namespace: tekton-pipelines roleRef: kind: Role - name: cel-controller + name: tekton-cel-controller + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: RoleBinding +metadata: + name: tekton-cel-webhook + namespace: tekton-pipelines + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +subjects: + - kind: ServiceAccount + name: tekton-cel-webhook + namespace: tekton-pipelines +roleRef: + kind: Role + name: tekton-cel-webhook apiGroup: rbac.authorization.k8s.io diff --git a/cel/config/202-clusterrolebinding.yaml b/cel/config/202-clusterrolebinding.yaml index 9b27c976a..0f878357c 100644 --- a/cel/config/202-clusterrolebinding.yaml +++ b/cel/config/202-clusterrolebinding.yaml @@ -15,16 +15,88 @@ apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: - name: cel-controller-cluster-access + name: tekton-cel-controller-cluster-access labels: - app.kubernetes.io/component: cel-controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run + app.kubernetes.io/part-of: tekton-cel subjects: - kind: ServiceAccount - name: cel-controller - namespace: tekton-cel-run + name: tekton-cel-controller + namespace: tekton-pipelines roleRef: kind: ClusterRole - name: cel-controller-cluster-access + name: tekton-cel-controller-cluster-access + apiGroup: rbac.authorization.k8s.io +--- +# If this ClusterRoleBinding is replaced with a RoleBinding +# then the ClusterRole would be namespaced. The access described by +# the tekton-cel-controller-tenant-access ClusterRole would +# be scoped to individual tenant namespaces. +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: tekton-cel-controller-tenant-access + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +subjects: + - kind: ServiceAccount + name: tekton-cel-controller + namespace: tekton-pipelines +roleRef: + kind: ClusterRole + name: tekton-cel-controller-tenant-access + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: tekton-cel-controller-leaderelection + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +subjects: + - kind: ServiceAccount + name: tekton-cel-controller + namespace: tekton-pipelines +roleRef: + kind: ClusterRole + name: tekton-cel-leader-election + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: tekton-cel-webhook-cluster-access + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +subjects: + - kind: ServiceAccount + name: tekton-cel-webhook + namespace: tekton-pipelines +roleRef: + kind: ClusterRole + name: tekton-cel-webhook-cluster-access + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRoleBinding +metadata: + name: tekton-cel-webhook-leaderelection + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +subjects: + - kind: ServiceAccount + name: tekton-cel-webhook + namespace: tekton-pipelines +roleRef: + kind: ClusterRole + name: tekton-cel-leader-election apiGroup: rbac.authorization.k8s.io diff --git a/cel/config/300-cel.yaml b/cel/config/300-cel.yaml new file mode 100644 index 000000000..35aa9e1d8 --- /dev/null +++ b/cel/config/300-cel.yaml @@ -0,0 +1,50 @@ +# Copyright 2021 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: cels.custom.tekton.dev + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +spec: + group: custom.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: CEL + plural: cels + categories: + - tekton + - tekton-pipelines + scope: Namespaced + # Opt into the status subresource so metadata.generation + # starts to increment + subresources: + status: {} diff --git a/cel/config/400-controller-service.yaml b/cel/config/400-controller-service.yaml deleted file mode 100644 index bd3c9429b..000000000 --- a/cel/config/400-controller-service.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright 2021 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.kubernetes.io/name: cel-controller - app.kubernetes.io/component: cel-controller - app.kubernetes.io/instance: default - app.kubernetes.io/version: devel - app.kubernetes.io/part-of: tekton-cel-run - # tekton.dev/release value replaced with inputs.params.versionTag in pipeline/tekton/publish.yaml - pipeline.tekton.dev/release: "devel" - # labels below are related to istio and should not be used for resource lookup - app: cel-controller - version: "devel" - name: cel-controller - namespace: tekton-cel-run -spec: - ports: - - name: http-metrics - port: 9090 - protocol: TCP - targetPort: 9090 - selector: - app.kubernetes.io/name: cel-controller - app.kubernetes.io/component: cel-controller - app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run diff --git a/cel/config/500-controller.yaml b/cel/config/500-controller.yaml index fed9c1927..803ea09d8 100644 --- a/cel/config/500-controller.yaml +++ b/cel/config/500-controller.yaml @@ -15,52 +15,49 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: cel-controller - namespace: tekton-cel-run + name: tekton-cel-controller + namespace: tekton-pipelines labels: - app.kubernetes.io/name: cel-controller - app.kubernetes.io/component: cel-controller + app.kubernetes.io/name: controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/version: devel - app.kubernetes.io/part-of: tekton-cel-run + app.kubernetes.io/part-of: tekton-cel spec: replicas: 1 selector: matchLabels: - app.kubernetes.io/name: cel-controller - app.kubernetes.io/component: cel-controller + app.kubernetes.io/name: controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/part-of: cel + app.kubernetes.io/part-of: tekton-cel template: metadata: annotations: cluster-autoscaler.kubernetes.io/safe-to-evict: "false" labels: - app.kubernetes.io/name: cel-controller - app.kubernetes.io/component: cel-controller + app.kubernetes.io/name: controller + app.kubernetes.io/component: controller app.kubernetes.io/instance: default - app.kubernetes.io/version: devel - app.kubernetes.io/part-of: cel - app: cel-controller + app.kubernetes.io/part-of: tekton-cel + app: tekton-cel-controller spec: - serviceAccountName: cel-controller + serviceAccountName: tekton-cel-controller containers: - - name: cel-controller - image: ko://github.com/tektoncd/experimental/cel/cmd/controller - volumeMounts: - - name: config-logging - mountPath: /etc/config-logging - env: - - name: SYSTEM_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - # If you are changing these names, you will also need to update - # the controller's Role in 200-role.yaml to include the new - # values in the "configmaps" "get" rule. - - name: CONFIG_LOGGING_NAME - value: config-logging - volumes: - - name: config-logging - configMap: - name: config-logging + - name: tekton-cel-controller + image: ko://github.com/tektoncd/experimental/cel/cmd/controller + env: + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: CONFIG_LEADERELECTION_NAME + value: config-leader-election + - name: CONFIG_LOGGING_NAME + value: config-logging + - name: CONFIG_OBSERVABILITY_NAME + value: config-observability + - name: METRICS_DOMAIN + value: tekton.dev/pipeline + securityContext: + allowPrivilegeEscalation: false + runAsUser: 1001 diff --git a/cel/config/500-webhook-configuration.yaml b/cel/config/500-webhook-configuration.yaml new file mode 100644 index 000000000..8cf81c792 --- /dev/null +++ b/cel/config/500-webhook-configuration.yaml @@ -0,0 +1,62 @@ +# Copyright 2021 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: tekton-cel-webhook-certs + namespace: tekton-pipelines + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +--- +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +metadata: + name: validation.webhook.cel.custom.tekton.dev + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: tekton-cel-webhook + namespace: tekton-pipelines + failurePolicy: Fail + sideEffects: None + name: validation.webhook.cel.custom.tekton.dev + +--- +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: webhook.cel.custom.tekton.dev + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +webhooks: +- admissionReviewVersions: + - v1beta1 + clientConfig: + service: + name: tekton-cel-webhook + namespace: tekton-pipelines + failurePolicy: Fail + sideEffects: None + name: webhook.cel.custom.tekton.dev diff --git a/cel/config/500-webhook.yaml b/cel/config/500-webhook.yaml new file mode 100644 index 000000000..eca33bfe0 --- /dev/null +++ b/cel/config/500-webhook.yaml @@ -0,0 +1,106 @@ +# Copyright 2021 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: apps/v1 +kind: Deployment +metadata: + name: tekton-cel-webhook + namespace: tekton-pipelines + labels: + app.kubernetes.io/name: webhook + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: webhook + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel + template: + metadata: + annotations: + cluster-autoscaler.kubernetes.io/safe-to-evict: "false" + labels: + app.kubernetes.io/name: webhook + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel + app: tekton-cel-webhook + spec: + serviceAccountName: tekton-cel-webhook + containers: + - name: webhook + image: ko://github.com/tektoncd/experimental/cel/cmd/webhook + env: + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + # If you are changing these names, you will also need to update + # the webhook's Role in 200-role.yaml to include the new + # values in the "configmaps" "get" rule. + - name: CONFIG_LOGGING_NAME + value: config-logging + - name: CONFIG_OBSERVABILITY_NAME + value: config-observability + - name: CONFIG_LEADERELECTION_NAME + value: config-leader-election + - name: WEBHOOK_SERVICE_NAME + value: tekton-cel-webhook + - name: WEBHOOK_SECRET_NAME + value: tekton-cel-webhook-certs + - name: METRICS_DOMAIN + value: tekton.dev/pipeline + securityContext: + allowPrivilegeEscalation: false + runAsUser: 1001 + ports: + - name: metrics + containerPort: 9090 + - name: profiling + containerPort: 8008 + - name: https-webhook + containerPort: 8443 +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: webhook + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel + app: tekton-cel-webhook + name: tekton-cel-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: + app.kubernetes.io/name: webhook + app.kubernetes.io/component: webhook + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-cel diff --git a/cel/config/config-logging.yaml b/cel/config/config-logging.yaml deleted file mode 100644 index eee518b8a..000000000 --- a/cel/config/config-logging.yaml +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright 2021 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: ConfigMap -metadata: - name: config-logging - namespace: tekton-cel-run - labels: - app.kubernetes.io/instance: default - app.kubernetes.io/part-of: tekton-cel-run -data: - # Common configuration for all knative codebase - zap-logger-config: | - { - "level": "info", - "development": false, - "sampling": { - "initial": 100, - "thereafter": 100 - }, - "outputPaths": ["stdout"], - "errorOutputPaths": ["stderr"], - "encoding": "json", - "encoderConfig": { - "timeKey": "", - "levelKey": "level", - "nameKey": "logger", - "callerKey": "caller", - "messageKey": "msg", - "stacktraceKey": "stacktrace", - "lineEnding": "", - "levelEncoder": "", - "timeEncoder": "", - "durationEncoder": "", - "callerEncoder": "" - } - } - - # Log level overrides - loglevel.controller: "info" - loglevel.webhook: "info" diff --git a/cel/examples/celrun-is-red.yaml b/cel/examples/celrun-colors.yaml similarity index 70% rename from cel/examples/celrun-is-red.yaml rename to cel/examples/celrun-colors.yaml index eef4c346f..b607203b8 100644 --- a/cel/examples/celrun-is-red.yaml +++ b/cel/examples/celrun-colors.yaml @@ -1,12 +1,9 @@ -apiVersion: tekton.dev/v1alpha1 -kind: Run +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL metadata: - generateName: celrun-is-red- + name: colors spec: - ref: - apiVersion: cel.tekton.dev/v1alpha1 - kind: CEL - params: + expressions: - name: red value: "{'blue': '0x000080', 'red': '0xFF0000'}['red']" - name: blue @@ -15,3 +12,13 @@ spec: value: "{'blue': '0x000080', 'red': '0xFF0000'}['red'] == '0xFF0000'" - name: is-blue value: "{'blue': '0x000080', 'red': '0xFF0000'}['blue'] == '0xFF0000'" +--- +apiVersion: tekton.dev/v1alpha1 +kind: Run +metadata: + generateName: colors- +spec: + ref: + apiVersion: custom.tekton.dev/v1alpha1 + kind: CEL + name: colors diff --git a/cel/examples/celrun-get-type.yaml b/cel/examples/celrun-get-type.yaml index a49efabf3..970e43da3 100644 --- a/cel/examples/celrun-get-type.yaml +++ b/cel/examples/celrun-get-type.yaml @@ -1,11 +1,18 @@ +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-type +spec: + expressions: + - name: expression + value: "type(1)" +--- apiVersion: tekton.dev/v1alpha1 kind: Run metadata: - generateName: celrun-get-type- + generateName: get-type- spec: ref: - apiVersion: cel.tekton.dev/v1alpha1 + apiVersion: custom.tekton.dev/v1alpha1 kind: CEL - params: - - name: expression - value: "type(1)" + name: get-type diff --git a/cel/examples/celrun-sevs.yaml b/cel/examples/celrun-sevs.yaml new file mode 100644 index 000000000..8fa701afd --- /dev/null +++ b/cel/examples/celrun-sevs.yaml @@ -0,0 +1,23 @@ +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: sevs +spec: + variables: + - name: job_priority + value: "high" + - name: alert_enable + value: "true" + expressions: + - name: job_severity + value: "job_priority in ['high', 'normal'] ? 'sev-1' : 'sev-2'" +--- +apiVersion: tekton.dev/v1alpha1 +kind: Run +metadata: + generateName: sevs- +spec: + ref: + apiVersion: custom.tekton.dev/v1alpha1 + kind: CEL + name: sevs diff --git a/cel/examples/pipelinerun-celruns.yaml b/cel/examples/pipelinerun-celruns.yaml index 48d22e6a8..0c49fe6b1 100644 --- a/cel/examples/pipelinerun-celruns.yaml +++ b/cel/examples/pipelinerun-celruns.yaml @@ -1,3 +1,21 @@ +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: is-red +spec: + expressions: + - name: red + value: "{'blue': '0x000080', 'red': '0xFF0000'}['red'] == '0xFF0000'" +--- +apiVersion: custom.tekton.dev/v1alpha1 +kind: CEL +metadata: + name: get-type +spec: + expressions: + - name: type + value: "type(1)" +--- apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: @@ -5,26 +23,12 @@ metadata: spec: serviceAccountName: 'default' pipelineSpec: - params: - - name: red - type: string - - name: type - type: string tasks: - name: is-red taskRef: - apiVersion: cel.tekton.dev/v1alpha1 - kind: CEL - params: - - name: red - value: "$(params.red)" - - name: get-type - taskRef: - apiVersion: cel.tekton.dev/v1alpha1 + apiVersion: custom.tekton.dev/v1alpha1 kind: CEL - params: - - name: type - value: "$(params.type)" + name: is-red - name: echo-is-red when: - input: "$(tasks.is-red.results.red)" @@ -35,6 +39,11 @@ spec: - name: echo image: ubuntu script: echo ISRED! + - name: get-type + taskRef: + apiVersion: custom.tekton.dev/v1alpha1 + kind: CEL + name: get-type - name: echo-get-type when: - input: "$(tasks.get-type.results.type)" @@ -45,8 +54,3 @@ spec: - name: echo image: ubuntu script: echo ISINT! - params: - - name: red - value: "{'blue': '0x000080', 'red': '0xFF0000'}['red'] == '0xFF0000'" - - name: type - value: "type(1)" diff --git a/cel/go.mod b/cel/go.mod index 2ced0b5d0..f37ab3787 100644 --- a/cel/go.mod +++ b/cel/go.mod @@ -3,29 +3,22 @@ module github.com/tektoncd/experimental/cel go 1.15 require ( - github.com/google/cel-go v0.7.0 - github.com/google/go-cmp v0.5.4 - github.com/tektoncd/pipeline v0.20.0 + github.com/ghodss/yaml v1.0.0 + github.com/google/cel-go v0.7.3 + github.com/google/go-cmp v0.5.5 + github.com/hashicorp/go-multierror v1.1.0 + github.com/tektoncd/pipeline v0.24.0 + go.opencensus.io v0.23.0 go.uber.org/zap v1.16.0 - k8s.io/api v0.20.2 - k8s.io/apimachinery v0.18.12 - k8s.io/client-go v11.0.1-0.20190805182717-6502b5e7b1b5+incompatible - knative.dev/pkg v0.0.0-20210114223020-f0ea5e6b9c4e + google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de + k8s.io/api v0.20.7 + k8s.io/apimachinery v0.20.7 + k8s.io/client-go v0.20.7 + knative.dev/pkg v0.0.0-20210510175900-4564797bf3b7 ) // Knative deps replace ( contrib.go.opencensus.io/exporter/stackdriver => contrib.go.opencensus.io/exporter/stackdriver v0.12.9-0.20191108183826-59d068f8d8ff github.com/Azure/azure-sdk-for-go => github.com/Azure/azure-sdk-for-go v38.2.0+incompatible - github.com/Azure/go-autorest => github.com/Azure/go-autorest v13.4.0+incompatible -) - -// Pin k8s deps to v0.18.8 -replace ( - k8s.io/api => k8s.io/api v0.18.8 - k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.18.8 - k8s.io/apimachinery => k8s.io/apimachinery v0.18.8 - k8s.io/client-go => k8s.io/client-go v0.18.8 - k8s.io/code-generator => k8s.io/code-generator v0.18.8 - k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29 ) diff --git a/cel/go.sum b/cel/go.sum index c1e96cd3f..4930e6271 100644 --- a/cel/go.sum +++ b/cel/go.sum @@ -1,19 +1,18 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.64.0/go.mod h1:xfORb36jGvE+6EexW71nMEtL025s3x6xvuYUKM4JLv4= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0 h1:eWRCuwubtDrCJG0oSUMgnsbD4CmPFQF2ei4OFbXvwww= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= @@ -34,57 +33,54 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.11.0/go.mod h1:/PAbprKS+5msVYogBmczjWalDXnQ9mr64yEq9YnyPeo= contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d h1:LblfooH1lKOpp1hIhukktmSAxFkqMPFk9KR6iZ0MJNI= contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d/go.mod h1:IshRmMJBhDfFj5Y67nVhMYTTIze91RUeT73ipWKs/GY= -contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0 h1:2O3c1g5CzMc1+Uah4Waot9Obm0yw70VXJzWaP6Fz3nw= contrib.go.opencensus.io/exporter/prometheus v0.2.1-0.20200609204449-6bcf6f8577f0/go.mod h1:MjHoxkI7Ny27toPeFkRbXbzVjzIGkwOAptrAy8Mxtm8= +contrib.go.opencensus.io/exporter/prometheus v0.3.0 h1:08FMdJYpItzsknogU6PiiNo7XQZg/25GjH236+YCwD0= +contrib.go.opencensus.io/exporter/prometheus v0.3.0/go.mod h1:rpCPVQKhiyH8oomWgm34ZmgIdZa8OVYO5WAIygPbBBE= contrib.go.opencensus.io/exporter/stackdriver v0.12.9-0.20191108183826-59d068f8d8ff h1:g4QkFNN0ak+sCs/jqbhYLNkQaF1NVaKVoQ4Xm1RV3wM= contrib.go.opencensus.io/exporter/stackdriver v0.12.9-0.20191108183826-59d068f8d8ff/go.mod h1:XyyafDnFOsqoxHJgTFycKZMrRUrPThLh2iYTJF6uoO0= contrib.go.opencensus.io/exporter/zipkin v0.1.2/go.mod h1:mP5xM3rrgOjpn79MM8fZbj3gsxcuytSqtH0dxSWW1RE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/Azure/azure-sdk-for-go v38.2.0+incompatible h1:ZeCdp1E/V5lI8oLR/BjWQh0OW9aFBYlgXGKRVIWNPXY= github.com/Azure/azure-sdk-for-go v38.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-autorest v13.4.0+incompatible h1:YI49AKujDVk2KcLPKYGfkP7DlwU1xlRdI8GA0JWVYvE= -github.com/Azure/go-autorest v13.4.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= -github.com/Azure/go-autorest/autorest v0.10.2 h1:NuSF3gXetiHyUbVdneJMEVyPUYAe5wh+aN08JYAf1tI= -github.com/Azure/go-autorest/autorest v0.10.2/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= -github.com/Azure/go-autorest/autorest/adal v0.8.2 h1:O1X4oexUxnZCaEUGsvMnr8ZGj8HI37tNezwY4npRqA0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5 h1:Y3bBUV4rTuxenJJs41HU3qmqsb+auo+a3Lz+PlJPpL0= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/to v0.3.0 h1:zebkZaadz7+wIQYgC7GXaz3Wb28yKYfVkkBKwc38VF8= github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +github.com/Azure/go-autorest/autorest/validation v0.1.0 h1:ISSNzGUh+ZSzizJWOWzs8bwpXIePbGLW4z/AmUFGH5A= github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= -github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= -github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= +github.com/Azure/go-autorest/logger v0.2.0 h1:e4RVHVZKC5p6UANLJHkM4OfR1UKZPj8Wt8Pcx+3oqrE= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/GoogleCloudPlatform/cloud-builders/gcs-fetcher v0.0.0-20191203181535-308b93ad1f39/go.mod h1:yfGmCjKuUzk9WzubMlW2zwjhCraIc/J+M40cufdemRM= -github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= +github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317/go.mod h1:DF8FZRxMHMGv/vP2lQP6h+dYzzjpuRn24VeRiYn3qjQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -97,7 +93,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/sarama v1.23.1/go.mod h1:XLH1GYJnLVE0XCr6KdJGVJRTwY30moWNJ4sERjXX6fs= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= @@ -130,7 +125,6 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.28.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.31.6/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.31.12 h1:SxRRGyhlCagI0DYkhOg+FgdXGXzRTE3vEX/gsgFaiKQ= github.com/aws/aws-sdk-go v1.31.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= @@ -165,10 +159,12 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cloudevents/sdk-go/v2 v2.1.0 h1:bmgrU8k+K2ppZ+G/q5xEQx/Xk9HRtJmkrEO3qtDO2k0= github.com/cloudevents/sdk-go/v2 v2.1.0/go.mod h1:3CTrpB4+u7Iaj6fd7E2Xvm5IxMdRoaAhqaRVnOr2rCU= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/stargz-snapshotter/estargz v0.0.0-20201223015020-a9a0c2d64694 h1:OVQ4FVXeE6OjzuUifzER+7EulqTqw/94oKSqnooEowQ= +github.com/containerd/stargz-snapshotter/estargz v0.0.0-20201223015020-a9a0c2d64694/go.mod h1:E9uVkkBKf0EaC39j2JVW9EzdNhYvpz6eQIjILHebruk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= @@ -178,7 +174,6 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -188,7 +183,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-gk v0.0.0-20140819190930-201884a44051/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= github.com/dgryski/go-gk v0.0.0-20200319235926-a69029f61654/go.mod h1:qm+vckxRlDt0aOla0RYJJVeqHZlWfOm2UIxHaqPB46E= @@ -196,9 +190,14 @@ github.com/dgryski/go-lttb v0.0.0-20180810165845-318fcdf10a77/go.mod h1:Va5MyIzk github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.2+incompatible h1:CR/6BZX5w3TLgAHZTyRpVh3yi+Q8Sj5j1fCsb0J2rCk= +github.com/docker/cli v20.10.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.2+incompatible h1:vFgEHPqWBTp4pTjdLwjAA4bSo3gvIGOYwuJTlEjVBCw= +github.com/docker/docker v20.10.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -208,24 +207,27 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3 github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.15.0+incompatible h1:8KpYO/Xl/ZudZs5RNOEhWMBY4hmzlZhhRd9cu+jrZP4= +github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc= -github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= @@ -250,8 +252,10 @@ github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgO github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -264,14 +268,16 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+ github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -285,8 +291,9 @@ github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.6 h1:rMMMj8cV38KVXK7SFc+I2MWClbEfbK705+j+dyqun5g= github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/spec v0.20.2 h1:pFPUZsiIbZ20kLUcuCGeuQWG735fPMxW7wHF9BWlnQU= +github.com/go-openapi/spec v0.20.2/go.mod h1:RW6Xcbs6LOyWLU/mXGdzn2Qc+3aj+ASfI7rvSZh1Vls= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= @@ -296,24 +303,25 @@ github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/ github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.7 h1:VRuXN2EnMSsZdauzdss6JBC29YotDqG59BZ+tdlIL1s= github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= +github.com/go-openapi/swag v0.19.13 h1:233UVgMy1DlmCYYfOiFpta6e2urloh+sEs5id6lyzog= +github.com/go-openapi/swag v0.19.13/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/envy v1.6.5/go.mod h1:N+GkhhZ/93bGZc6ZKhJLP6+m+tCNPKwgSpH9kaifseQ= -github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/flect v0.2.2 h1:PAVD7sp0KOdfswjAw9BpLCU9hXo7wFSzgpQ+zNeks/A= +github.com/gobuffalo/flect v0.2.2/go.mod h1:vmkQwuZYhN5Pc4ljYQZzP+1sq+NEkK+lh20jmEmX3jc= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48 h1:X+zN6RZXsvnrSJaAIQhZezPfAfvsqihKKR8oiLHid34= -github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -329,7 +337,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -343,10 +350,11 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= github.com/gonum/diff v0.0.0-20181124234638-500114f11e71/go.mod h1:22dM4PLscQl+Nzf64qNBurVJvfyvZELT0iRW2l/NN70= github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= @@ -358,8 +366,8 @@ github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP github.com/gonum/stat v0.0.0-20181125101827-41a0da705a5b/go.mod h1:Z4GIJBJO3Wa4gD4vbwQxXXZ+WHmW6E9ixmNrwvs0iZs= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/cel-go v0.7.0 h1:J0J8RSCJW+SdB53YPwPSm2m1Kfz1tqGXdwMuIAVRU9o= -github.com/google/cel-go v0.7.0/go.mod h1:4EtyFAHT5xNr0Msu0MJjyGxPUgdr9DlcaPyzLt/kkt8= +github.com/google/cel-go v0.7.3 h1:8v9BSN0avuGwrHFKNCjfiQ/CE6+D6sW+BDyOVoEeP6o= +github.com/google/cel-go v0.7.3/go.mod h1:4EtyFAHT5xNr0Msu0MJjyGxPUgdr9DlcaPyzLt/kkt8= github.com/google/cel-spec v0.5.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -369,16 +377,21 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-containerregistry v0.2.1 h1:LLZgLTDguTVJ9eEHh/zTtr347CpFhH6MSYculNas5bY= -github.com/google/go-containerregistry v0.2.1/go.mod h1:Ts3Wioz1r5ayWx8sS6vLcWltWcM1aqFjd/eVrkFhrWM= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-containerregistry v0.4.1-0.20210128200529-19c2b639fab1 h1:o2ykCuuhHeUwtzNg89pH2hi+821aqjLWkaREVR3ziTQ= +github.com/google/go-containerregistry v0.4.1-0.20210128200529-19c2b639fab1/go.mod h1:GU9FUA/X9rd2cV3ZoUNaWihp27tki6/38EsVzL2Dyzc= +github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20210129212729-5c4818de4025 h1:3o5qj2tOnL5eMB9b8YbcJ25sJI8oLrfy6Z0YYZl6lGY= +github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20210129212729-5c4818de4025/go.mod h1:n9wRxRfKkHy6ZFyj0jJQHw11P+mGLnED4sqegwrXxDk= github.com/google/go-github/v27 v27.0.6/go.mod h1:/0Gr8pJ55COkmv+S/yPKCczSkUPIM/LnFyubufRNIS0= github.com/google/go-licenses v0.0.0-20200602185517-f29a4c695c3d/go.mod h1:g1VOUGKZYIqe8lDq2mL7plhAWXqrEaGUs7eIjthN1sk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licenseclassifier v0.0.0-20190926221455-842c0d70d702/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3/go.mod h1:YzLcVlL+NqWnmUEPuhS1LxDDwGO9WNbVlEXaF4IH35g= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -386,7 +399,6 @@ github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIG github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -396,19 +408,16 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww= -github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.4.0 h1:BXDUo8p/DaxC+4FJY/SSx3gvnx9C1VdHNgaUkiEL5mk= -github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= -github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.3 h1:2qsuRm+bzgwSIKikigPASa2GhW8H2Dn4Qq7UxD8K/48= +github.com/googleapis/gnostic v0.5.3/go.mod h1:TRWw1s4gxBGjSe301Dai3c7wXJAZy57+/6tawkOvqHQ= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -467,20 +476,20 @@ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod github.com/influxdata/tdigest v0.0.0-20180711151920-a7d76c6f093a/go.mod h1:9GkyshztGufsdPQWjH+ifgnIr3xNUL5syI70g2dzU1o= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= -github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jenkins-x/go-scm v1.5.117/go.mod h1:PCT338UhP/pQ0IeEeMEf/hoLTYKcH7qjGEKd7jPkeYg= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= -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/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -494,13 +503,13 @@ github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= @@ -519,26 +528,29 @@ github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.1-0.20191009090205-6c0755d89d1e h1:jcoUdG1TzY/M/eM5BLFLP8DJeMximx5NQYSlLL9YeWc= github.com/mailru/easyjson v0.7.1-0.20191009090205-6c0755d89d1e/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/markbates/inflect v1.0.4/go.mod h1:1fR9+pO2KHEO9ZRtto13gDwwZaAKstQzferVeWqbgNs= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -582,10 +594,13 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= @@ -593,9 +608,9 @@ github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.0/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.5 h1:UwtQQx2pyPIgWYHRg+epgdx1/HnBQTgN3/oIYEJTQzU= github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -609,10 +624,8 @@ github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtb github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4 v2.2.6+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -626,12 +639,13 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.8.0 h1:zvJNkoCFAnYFNC24FV8nW4JdRJ3GIFcLbg65lL/JDcw= -github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= +github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg= +github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -643,34 +657,35 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= -github.com/prometheus/common v0.15.0 h1:4fgOnadei3EZvgRwxJ7RMpG1k1pOZth5Pc13tyspaKM= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.19.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.20.0 h1:pfeDeUdQcIxOMutNjCejsEFp7qeP+/iltHSSmLpE+hU= +github.com/prometheus/common v0.20.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.6/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/statsd_exporter v0.15.0 h1:UiwC1L5HkxEPeapXdm2Ye0u1vUJfTj7uwT5yydYpa1E= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/statsd_exporter v0.15.0/go.mod h1:Dv8HnkoLQkeEjkIE4/2ndAA7WL1zHKK7WMqFQqu72rw= +github.com/prometheus/statsd_exporter v0.20.0 h1:M0hQphnq2WyWKS5CefQL8PqWwBOBPhiAkyLo5l4ZYvE= +github.com/prometheus/statsd_exporter v0.20.0/go.mod h1:YL3FWCG8JBBtaUSxAg4Gz2ZYu22bS84XM89ZQXXTWmQ= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rcrowley/go-metrics v0.0.0-20190706150252-9beb055b7962/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= +github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -685,8 +700,9 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -719,11 +735,12 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/tektoncd/pipeline v0.20.0 h1:JW9YgkzQAvW2vzU1zpwyz3IALqzyMNBnfLOzz88mZ0A= -github.com/tektoncd/pipeline v0.20.0/go.mod h1:xF5WxMLvp/05oGZ+Fvqcbglmf4HVU9u1keXHaM+rR14= -github.com/tektoncd/plumbing v0.0.0-20201021153918-6b7e894737b5/go.mod h1:WTWwsg91xgm+jPOKoyKVK/yRYxnVDlUYeDlypB1lDdQ= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tektoncd/pipeline v0.24.0 h1:gdUAJ/7fmA3imZtk+Mrwo5L34imNr3YLR4SfN0OzzBk= +github.com/tektoncd/pipeline v0.24.0/go.mod h1:ChFD/vfu14VOtCVlLWdtlvOwXfBfVotULoNV6yz+CKY= +github.com/tektoncd/plumbing v0.0.0-20210420200944-17170d5e7bc9/go.mod h1:WTWwsg91xgm+jPOKoyKVK/yRYxnVDlUYeDlypB1lDdQ= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= @@ -735,12 +752,11 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/vdemeester/k8s-pkg-credentialprovider v1.18.1-0.20201019120933-f1d16962a4db/go.mod h1:grWy0bkr1XO6hqbaaCKaPXqkBVlMGHYG6PGykktwbJc= +github.com/vdemeester/k8s-pkg-credentialprovider v1.19.7 h1:MJ5fV2Z0OyIuPvFVs0vi6VjTjxpdK1QT8oX/aWiUjYM= +github.com/vdemeester/k8s-pkg-credentialprovider v1.19.7/go.mod h1:K2nMO14cgZitdwBqdQps9tInJgcaXcU/7q5F59lpbNI= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= -github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -749,7 +765,9 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= @@ -762,16 +780,17 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4-0.20200608061201-1901b56b9515/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/automaxprocs v1.3.0 h1:II28aZoGdaglS5vVNnspf28lnZpXScxtIozx1lAjdb0= -go.uber.org/automaxprocs v1.3.0/go.mod h1:9CWT6lKIep8U41DDaPiH6eFscnTyjfTANNQNx6LrIcA= +go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0= +go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= @@ -789,7 +808,6 @@ golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -799,15 +817,15 @@ golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc h1:+q90ECDSAQirdykUN6sPEiBXBsp8Csjcca8Oy7bgLTA= +golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= @@ -826,19 +844,19 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20190806162312-597adff16ade/go.mod h1:AlhUtkH4DA4asiFC5RgK7ZKmauvtkAVcy9L0epCzlWo= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -865,7 +883,6 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190912160710-24e19bdeb0f2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -881,12 +898,17 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d h1:BgJvlyh+UqCUaPlscHJ+PN8GcpfrFdr7NHjd1JL0+Gs= +golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -894,8 +916,10 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78 h1:rPRtHfUb0UKZeZ6GH4K4Nt4YRbE9V1u+QZX5upZXqJQ= +golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -905,9 +929,9 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -922,7 +946,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -932,15 +955,13 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191119060738-e882bf8e40c2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -949,6 +970,7 @@ golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -956,6 +978,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -965,26 +988,39 @@ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3 h1:kzM6+9dur93BcC2kVlYl34cHU+TYZLanmpSJHVMmL64= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M= +golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1005,14 +1041,13 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190807223507-b346f7fd45de/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1037,20 +1072,23 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200817023811-d00afeaade8f/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200827163409-021d7c6f1ec3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag= -golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1062,7 +1100,6 @@ gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJ gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1070,6 +1107,8 @@ google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhE google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.1-0.20200106000736-b8fc810ca6b5/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.1/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= @@ -1099,7 +1138,6 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1125,15 +1163,15 @@ google.golang.org/genproto v0.0.0-20200527145253-8367513e4ece/go.mod h1:jDfRM7Fc google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200815001618-f69a88009b70/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200827165113-ac2560b5e952/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201211151036-40ec1c210f7a h1:GnJAhasbD8HiT8DZMvsEx3QLVy/X0icq/MGr0MqRJ2M= -google.golang.org/genproto v0.0.0-20201211151036-40ec1c210f7a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de h1:+nG/xknR+Gc5ByHOtK1dT0Pl3LYo8NLR+Jz3XeBeGEg= +google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1153,8 +1191,10 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1164,15 +1204,18 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/evanphx/json-patch.v4 v4.9.0 h1:T7W7A7+DTEpLTC11pkf8yfaeRfqhRj/gOPf+LtaJdNY= @@ -1180,13 +1223,9 @@ gopkg.in/evanphx/json-patch.v4 v4.9.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= -gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q= -gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= -gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM= -gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1204,62 +1243,85 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.5 h1:nI5egYTGJakVyOryqLs1cQO5dO0ksin5XXs2pspk75k= honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.18.8 h1:aIKUzJPb96f3fKec2lxtY7acZC9gQNDLVhfSGpxBAC4= -k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY= -k8s.io/apiextensions-apiserver v0.18.8 h1:pkqYPKTHa0/3lYwH7201RpF9eFm0lmZDFBNzhN+k/sA= -k8s.io/apiextensions-apiserver v0.18.8/go.mod h1:7f4ySEkkvifIr4+BRrRWriKKIJjPyg9mb/p63dJKnlM= -k8s.io/apimachinery v0.18.8 h1:jimPrycCqgx2QPearX3to1JePz7wSbVLq+7PdBTTwQ0= -k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig= -k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM= -k8s.io/client-go v0.18.8 h1:SdbLpIxk5j5YbFr1b7fq8S7mDgDjYmUxSbszyoesoDM= -k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU= -k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs= -k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c= -k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU= -k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4= -k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/api v0.19.7/go.mod h1:KTryDUT3l6Mtv7K2J2486PNL9DBns3wOYTkGR+iz63Y= +k8s.io/api v0.20.7 h1:wOEPJ3NoimUfR9v9sAO2JosPiEP9IGFNplf7zZvYzPU= +k8s.io/api v0.20.7/go.mod h1:4x0yErUkcEWYG+O0S4QdrYa2+PLEeY2M7aeQe++2nmk= +k8s.io/apiextensions-apiserver v0.19.7 h1:aV9DANMSCCYBEMbtoT/5oesrtcciQrjy9yqWVtZZL5A= +k8s.io/apiextensions-apiserver v0.19.7/go.mod h1:XJNNtjISNNePDEUClHt/igzMpQcmjVVh88QH+PKztPU= +k8s.io/apimachinery v0.0.0-20190703205208-4cfb76a8bf76/go.mod h1:M2fZgZL9DbLfeJaPBCDqSqNsdsmLN+V29knYJnIXlMA= +k8s.io/apimachinery v0.19.7/go.mod h1:6sRbGRAVY5DOCuZwB5XkqguBqpqLU6q/kOaOdk29z6Q= +k8s.io/apimachinery v0.20.7 h1:tBfhql7OggSCahvASeEpLRzvxc7FK77wNivi1uXCQWM= +k8s.io/apimachinery v0.20.7/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apiserver v0.19.7/go.mod h1:DmWVQggNePspa+vSsVytVbS3iBSDTXdJVt0akfHacKk= +k8s.io/client-go v0.19.7/go.mod h1:iytGI7S3kmv6bWnn+bSQUE4VlrEi4YFssvVB7J7Hvqg= +k8s.io/client-go v0.20.7 h1:Ot22456XfYAWrCWddw/quevMrFHqP7s1qT499FoumVU= +k8s.io/client-go v0.20.7/go.mod h1:uGl3qh/Jy3cTF1nDoIKBqUZlRWnj/EM+/leAXETKRuA= +k8s.io/cloud-provider v0.19.7/go.mod h1:aO/VpUwkG+JQN7ZXc5WBLZ5NBXuq/Y5B6vri6U94PZ8= +k8s.io/code-generator v0.19.7 h1:kM/68Y26Z/u//TFc1ggVVcg62te8A2yQh57jBfD0FWQ= +k8s.io/code-generator v0.19.7/go.mod h1:lwEq3YnLYb/7uVXLorOJfxg+cUu2oihFhHZ0n9NIla0= +k8s.io/component-base v0.19.7 h1:ZXS2VRWOWBOc2fTd1zjzhi/b/mkqFT9FDqiNsn1cH30= +k8s.io/component-base v0.19.7/go.mod h1:YX8spPBgwl3I6UGcSdQiEMAqRMSUsGQOW7SEr4+Qa3U= +k8s.io/csi-translation-lib v0.19.7/go.mod h1:WghizPQuzuygr2WdpgN2EjcNpDD2V4EAbxFXsgHgSBk= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw= +k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/klog/v2 v2.0.0 h1:Foj74zO6RbjjP4hBEKjnYtjjAhGg4jNynUdYF6fJrok= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29 h1:NeQXVJ2XFSkRoPzRo8AId01ZER+j8oV4SZADT4iBOXQ= -k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU= -k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGPF4on0IyICQE= -k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20200603063816-c1c6865ac451 h1:v8ud2Up6QK1lNOKFgiIVrZdMg7MpmSnvtrOieolJKoE= -k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -knative.dev/hack v0.0.0-20201214230143-4ed1ecb8db24/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= -knative.dev/pkg v0.0.0-20210107022335-51c72e24c179/go.mod h1:hckgW978SdzPA2H5EDvRPY8xsnPuDZLJLbPf8Jte7Q0= -knative.dev/pkg v0.0.0-20210114223020-f0ea5e6b9c4e h1:3k5tzvlM9VGZFiXRj8UKc3CUpMGpqBlEbIY0Dp3F3NU= -knative.dev/pkg v0.0.0-20210114223020-f0ea5e6b9c4e/go.mod h1:hckgW978SdzPA2H5EDvRPY8xsnPuDZLJLbPf8Jte7Q0= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.5.0 h1:8mOnjf1RmUPW6KRqQCfYSZq/K20Unmp3IhuZUhxl8KI= +k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kube-openapi v0.0.0-20210113233702-8566a335510f h1:ZcWbnalfwIst131Zff7dGd1HQdt+NA9q7z9Fi0vbsHY= +k8s.io/kube-openapi v0.0.0-20210113233702-8566a335510f/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/legacy-cloud-providers v0.19.7 h1:YJ/l/8/Hn56I9m1cudK8aNypRA/NvI/hYhg8fo/CTus= +k8s.io/legacy-cloud-providers v0.19.7/go.mod h1:dsZk4gH9QIwAtHQ8CK0Ps257xlfgoXE3tMkMNhW2xDU= +k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ= +k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +knative.dev/hack v0.0.0-20210325223819-b6ab329907d3/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= +knative.dev/hack v0.0.0-20210428122153-93ad9129c268 h1:lBIj9Epd9UQ55NEaHzAdY/UZbuaegCdGPKVC2+Z68Q0= +knative.dev/hack v0.0.0-20210428122153-93ad9129c268/go.mod h1:PHt8x8yX5Z9pPquBEfIj0X66f8iWkWfR0S/sarACJrI= +knative.dev/pkg v0.0.0-20210331065221-952fdd90dbb0/go.mod h1:PD5g8hUCXq6iR3tILjmZeJBvQfXGnHMPKryq54qHJhg= +knative.dev/pkg v0.0.0-20210510175900-4564797bf3b7 h1:i4P8emOPrLctmbaPHp5eRIOqz+XTOkit7KgZeS+onKs= +knative.dev/pkg v0.0.0-20210510175900-4564797bf3b7/go.mod h1:fIl4l4OmZodkElyaHoT0LCF5wT+3+P/kinawQ4XlLtE= pgregory.net/rapid v0.3.3/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= -sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.1-0.20200706213357-43c19bbb7fba h1:AAbnc5KQuTWKuh2QSnyghKIOTFzB0Jayv7/OFDn3Cy4= -sigs.k8s.io/structured-merge-diff/v3 v3.0.1-0.20200706213357-43c19bbb7fba/go.mod h1:V06abazjHneE37ZdSY/UUwPVgcJMKI/jU5XGUjgIKoc= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3 h1:4oyYo8NREp49LBBhKxEqCulFjg26rawYKrnCmg+Sr6c= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/cel/hack/boilerplate/boilerplate.go.txt b/cel/hack/boilerplate/boilerplate.go.txt new file mode 100644 index 000000000..a07160895 --- /dev/null +++ b/cel/hack/boilerplate/boilerplate.go.txt @@ -0,0 +1,15 @@ +/* +Copyright 2021 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. +*/ diff --git a/cel/hack/tools.go b/cel/hack/tools.go new file mode 100644 index 000000000..46018d4cd --- /dev/null +++ b/cel/hack/tools.go @@ -0,0 +1,8 @@ +//go:build tools +// +build tools + +package tools + +import ( + _ "knative.dev/pkg/hack" +) diff --git a/cel/hack/update-codegen.sh b/cel/hack/update-codegen.sh new file mode 100755 index 000000000..249057dab --- /dev/null +++ b/cel/hack/update-codegen.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +# Copyright 2021 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. + +set -o errexit +set -o nounset +set -o pipefail + +export GO111MODULE=on + +REPO_ROOT=$(dirname ${BASH_SOURCE})/.. +CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} + +KNATIVE_CODEGEN_PKG=${KNATIVE_CODEGEN_PKG:-$(cd ${REPO_ROOT}; ls -d -1 ./vendor/knative.dev/pkg 2>/dev/null || echo ../pkg)} + +# generate the code with: +# --output-base because this script should also be able to run inside the vendor dir of +# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir +# instead of the $GOPATH directly. For normal projects this can be dropped. +chmod +x ${CODEGEN_PKG}/generate-groups.sh +${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \ + github.com/tektoncd/experimental/cel/pkg/client github.com/tektoncd/experimental/cel/pkg/apis \ + "cel:v1alpha1" \ + --go-header-file ${REPO_ROOT}/hack/boilerplate/boilerplate.go.txt + +# Knative Injection + +chmod +x ${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh +${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh "injection" \ + github.com/tektoncd/experimental/cel/pkg/client github.com/tektoncd/experimental/cel/pkg/apis \ + "cel:v1alpha1" \ + --go-header-file ${REPO_ROOT}/hack/boilerplate/boilerplate.go.txt + +# Make sure our dependencies are up-to-date +${REPO_ROOT}/hack/update-deps.sh diff --git a/cel/hack/update-deps.sh b/cel/hack/update-deps.sh new file mode 100755 index 000000000..84e99510d --- /dev/null +++ b/cel/hack/update-deps.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# Copyright 2021 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 +# +# 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. + +readonly ROOT_DIR=$(dirname $0)/.. +source $(git rev-parse --show-toplevel)/vendor/github.com/tektoncd/plumbing/scripts/library.sh + +set -o errexit +set -o nounset +set -o pipefail + +export GO111MODULE=on +export GOFLAGS=-mod=vendor + +cd ${ROOT_DIR} + +VERSION="release-0.18" + +# The list of dependencies that we track at HEAD and periodically +# float forward in this repository. +FLOATING_DEPS=( + "knative.dev/pkg@${VERSION}" + "knative.dev/eventing@${VERSION}" + "knative.dev/test-infra@${VERSION}" +) + +# Parse flags to determine any we should pass to dep. +GO_GET=0 +while [[ $# -ne 0 ]]; do + parameter=$1 + case ${parameter} in + --upgrade) GO_GET=1 ;; + *) abort "unknown option ${parameter}" ;; + esac + shift +done +readonly GO_GET + +if (( GO_GET )); then + go get -d ${FLOATING_DEPS[@]} +fi + +# Prune modules. +go mod tidy +go mod vendor + +rm -rf $(find vendor/ -name 'OWNERS') +rm -rf $(find vendor/ -name '*_test.go') diff --git a/cel/pkg/apis/cel/controller.go b/cel/pkg/apis/cel/controller.go new file mode 100644 index 000000000..6e52ce988 --- /dev/null +++ b/cel/pkg/apis/cel/controller.go @@ -0,0 +1,22 @@ +/* +Copyright 2021 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 cel + +const ( + // ControllerName holds the name of the CEL controller + ControllerName = "CEL" +) diff --git a/cel/pkg/apis/cel/register.go b/cel/pkg/apis/cel/register.go new file mode 100644 index 000000000..8a1623e17 --- /dev/null +++ b/cel/pkg/apis/cel/register.go @@ -0,0 +1,22 @@ +/* +Copyright 2021 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 cel + +const ( + // GroupName is the Kubernetes resource group name for CEL types + GroupName = "custom.tekton.dev" +) diff --git a/cel/pkg/apis/cel/v1alpha1/cel_defaults.go b/cel/pkg/apis/cel/v1alpha1/cel_defaults.go new file mode 100644 index 000000000..e4ed9e850 --- /dev/null +++ b/cel/pkg/apis/cel/v1alpha1/cel_defaults.go @@ -0,0 +1,34 @@ +/* +Copyright 2021 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 = (*CEL)(nil) + +// SetDefaults set any defaults for the CEL +func (c *CEL) SetDefaults(ctx context.Context) { + c.Spec.SetDefaults(ctx) +} + +// SetDefaults set any defaults for the CEL spec +func (cs *CELSpec) SetDefaults(ctx context.Context) { +} diff --git a/cel/pkg/apis/cel/v1alpha1/cel_types.go b/cel/pkg/apis/cel/v1alpha1/cel_types.go new file mode 100644 index 000000000..57d6b1bc5 --- /dev/null +++ b/cel/pkg/apis/cel/v1alpha1/cel_types.go @@ -0,0 +1,96 @@ +/* +Copyright 2021 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 ( + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + "github.com/tektoncd/pipeline/pkg/apis/run/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:noStatus +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// CEL evaluates a CEL expression with given environment variables +// +k8s:openapi-gen=true +type CEL struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata"` + + // Spec holds the desired state of the CEL from the client + // +optional + Spec CELSpec `json:"spec"` +} + +// CELSpec defines the desired state of the CEL +type CELSpec struct { + // Variables to be configured in the CEL environment before evaluation + // +optional + Variables []*v1beta1.Param `json:"variables,omitempty"` + + // Expressions are a list of CEL expressions to be evaluated given the environment Variables + Expressions []*v1beta1.Param `json:"expressions"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// CELList contains a list of CELs +type CELList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + Items []CEL `json:"items"` +} + +// CELRunReason represents a reason for the Run "Succeeded" condition +type CELRunReason string + +const ( + // CELRunReasonFailedValidation indicates that the reason for failure status is that CEL failed validation + CELRunReasonFailedValidation CELRunReason = "RunValidationFailed" + + // CELRunReasonSyntaxError indicates that the reason for failure status is that a CEL expression couldn't be parsed + CELRunReasonSyntaxError CELRunReason = "SyntaxError" + + // CELRunReasonEvaluationError indicates that the reason for failure status is that a CEL expression couldn't be + // evaluated typically due to evaluation environment or executable program + CELRunReasonEvaluationError CELRunReason = "EvaluationError" + + // CELRunReasonEvaluationSuccess indicates that the reason for the success status is that all CEL expressions were + // evaluated successfully and the evaluation results were produced + CELRunReasonEvaluationSuccess CELRunReason = "EvaluationSuccess" + + // CELRunReasonCouldntGetCEL indicates that the reason for the failure status is that the Run could not find the CEL + CELRunReasonCouldntGetCEL CELRunReason = "CouldntGetCEL" + + // CELRunReasonInternalError indicates that the CEL failed due to an internal error in the reconciler + CELRunReasonInternalError CELRunReason = "InternalError" +) + +func (t CELRunReason) String() string { + return string(t) +} + +type CELStatus struct { + // Spec contains the exact spec used to instantiate the Run + Spec *CELSpec `json:"spec,omitempty"` + + // Results contains the results from evaluating the CEL expressions given the environment Variables + Results []v1alpha1.RunResult `json:"results,omitempty"` +} diff --git a/cel/pkg/apis/cel/v1alpha1/cel_validation.go b/cel/pkg/apis/cel/v1alpha1/cel_validation.go new file mode 100644 index 000000000..1bd5a3566 --- /dev/null +++ b/cel/pkg/apis/cel/v1alpha1/cel_validation.go @@ -0,0 +1,74 @@ +/* +Copyright 2021 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" + "fmt" + "github.com/tektoncd/pipeline/pkg/apis/validate" + "knative.dev/pkg/apis" +) + +var _ apis.Validatable = (*CEL)(nil) + +func (c *CEL) Validate(ctx context.Context) *apis.FieldError { + if err := validate.ObjectMetadata(c.GetObjectMeta()); err != nil { + return err.ViaField("metadata") + } + return c.Spec.Validate() +} + +func (cs *CELSpec) Validate() *apis.FieldError { + if err := validateCEL(cs); err != nil { + return err + } + return nil +} + +func validateCEL(cs *CELSpec) (errs *apis.FieldError) { + errs = errs.Also(validateExpressionsProvided(cs)) + errs = errs.Also(validateExpressionsType(cs)) + errs = errs.Also(validateVariablesType(cs)) + return errs +} + +func validateExpressionsProvided(cs *CELSpec) (errs *apis.FieldError) { + if len(cs.Expressions) == 0 { + errs = errs.Also(apis.ErrMissingField("expressions")) + } + return errs +} + +func validateExpressionsType(cs *CELSpec) (errs *apis.FieldError) { + for _, expression := range cs.Expressions { + if expression.Value.StringVal == "" { + errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("CEL expression %s must be a string", expression.Name), + "value").ViaFieldKey("expressions", expression.Name)) + } + } + return errs +} + +func validateVariablesType(cs *CELSpec) (errs *apis.FieldError) { + for _, variable := range cs.Variables { + if variable.Value.StringVal == "" { + errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("CEL environment variable %s must be a string", variable.Name), + "value").ViaFieldKey("variables", variable.Name)) + } + } + return errs +} diff --git a/cel/pkg/apis/cel/v1alpha1/cel_validation_test.go b/cel/pkg/apis/cel/v1alpha1/cel_validation_test.go new file mode 100644 index 000000000..151b175d5 --- /dev/null +++ b/cel/pkg/apis/cel/v1alpha1/cel_validation_test.go @@ -0,0 +1,147 @@ +/* +Copyright 2021 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" + celv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/tektoncd/pipeline/test/diff" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" +) + +func Test_CEL_Validate_Valid(t *testing.T) { + tests := []struct { + name string + cs *celv1alpha1.CEL + }{{ + name: "expressions only", + cs: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{Name: "cel"}, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{ + StringVal: "foo", + }, + }}, + }, + }, + }, { + name: "expressions and variables", + cs: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{Name: "cel"}, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{ + StringVal: "foo", + }, + }}, + Variables: []*v1beta1.Param{{ + Name: "var1", + Value: v1beta1.ArrayOrString{ + StringVal: "bar", + }, + }}, + }, + }, + }} + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.cs.Validate(context.Background()) + if err != nil { + t.Errorf("Unexpected error for %s: %s", tc.name, err) + } + }) + } +} + +func Test_CEL_Validate_Invalid(t *testing.T) { + tests := []struct { + name string + cs *celv1alpha1.CEL + expectedError apis.FieldError + }{{ + name: "no expressions", + cs: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{Name: "cel"}, + Spec: celv1alpha1.CELSpec{}, + }, + expectedError: apis.FieldError{ + Message: "missing field(s)", + Paths: []string{"expressions"}, + }, + }, { + name: "array expressions", + cs: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{Name: "cel"}, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{ + ArrayVal: []string{"foo", "bar"}, + }, + }}, + }, + }, + expectedError: apis.FieldError{ + Message: "invalid value: CEL expression expr1 must be a string", + Paths: []string{"expressions[expr1].value"}, + }, + }, { + name: "array variables", + cs: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{Name: "cel"}, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{ + StringVal: "foo", + }, + }}, + Variables: []*v1beta1.Param{{ + Name: "var1", + Value: v1beta1.ArrayOrString{ + ArrayVal: []string{"foo", "bar"}, + }, + }}, + }, + }, + expectedError: apis.FieldError{ + Message: "invalid value: CEL environment variable var1 must be a string", + Paths: []string{"variables[var1].value"}, + }, + }} + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + err := tc.cs.Validate(context.Background()) + if err == nil { + t.Errorf("Expected an Error but did not get one for %s", tc.name) + } else { + if d := cmp.Diff(tc.expectedError.Error(), err.Error(), cmpopts.IgnoreUnexported(apis.FieldError{})); d != "" { + t.Errorf("Error is different from expected for %s. diff %s", tc.name, diff.PrintWantGot(d)) + } + } + }) + } +} diff --git a/cel/pkg/apis/cel/v1alpha1/doc.go b/cel/pkg/apis/cel/v1alpha1/doc.go new file mode 100644 index 000000000..01a21ab50 --- /dev/null +++ b/cel/pkg/apis/cel/v1alpha1/doc.go @@ -0,0 +1,22 @@ +/* +Copyright 2021 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 contains API Schema definitions for the CEL v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +groupName=custom.tekton.dev +package v1alpha1 diff --git a/cel/pkg/apis/cel/v1alpha1/register.go b/cel/pkg/apis/cel/v1alpha1/register.go new file mode 100644 index 000000000..c633fb6de --- /dev/null +++ b/cel/pkg/apis/cel/v1alpha1/register.go @@ -0,0 +1,54 @@ +/* +Copyright 2021 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 ( + "github.com/tektoncd/experimental/cel/pkg/apis/cel" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: cel.GroupName, Version: "v1alpha1"} + +// Kind takes an unqualified kind and returns back a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + + // AddToScheme adds Build types to the scheme + AddToScheme = schemeBuilder.AddToScheme +) + +// Adds the list of known types to Scheme +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &CEL{}, + &CELList{}, + ) + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/cel/pkg/apis/cel/v1alpha1/zz_generated.deepcopy.go b/cel/pkg/apis/cel/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 000000000..7e4fb916a --- /dev/null +++ b/cel/pkg/apis/cel/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,152 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2021 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 deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + runv1alpha1 "github.com/tektoncd/pipeline/pkg/apis/run/v1alpha1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CEL) DeepCopyInto(out *CEL) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CEL. +func (in *CEL) DeepCopy() *CEL { + if in == nil { + return nil + } + out := new(CEL) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CEL) 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 *CELList) DeepCopyInto(out *CELList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]CEL, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CELList. +func (in *CELList) DeepCopy() *CELList { + if in == nil { + return nil + } + out := new(CELList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CELList) 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 *CELSpec) DeepCopyInto(out *CELSpec) { + *out = *in + if in.Variables != nil { + in, out := &in.Variables, &out.Variables + *out = make([]*v1beta1.Param, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(v1beta1.Param) + (*in).DeepCopyInto(*out) + } + } + } + if in.Expressions != nil { + in, out := &in.Expressions, &out.Expressions + *out = make([]*v1beta1.Param, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(v1beta1.Param) + (*in).DeepCopyInto(*out) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CELSpec. +func (in *CELSpec) DeepCopy() *CELSpec { + if in == nil { + return nil + } + out := new(CELSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CELStatus) DeepCopyInto(out *CELStatus) { + *out = *in + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(CELSpec) + (*in).DeepCopyInto(*out) + } + if in.Results != nil { + in, out := &in.Results, &out.Results + *out = make([]runv1alpha1.RunResult, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CELStatus. +func (in *CELStatus) DeepCopy() *CELStatus { + if in == nil { + return nil + } + out := new(CELStatus) + in.DeepCopyInto(out) + return out +} diff --git a/cel/pkg/client/clientset/versioned/clientset.go b/cel/pkg/client/clientset/versioned/clientset.go new file mode 100644 index 000000000..8cd905734 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/clientset.go @@ -0,0 +1,97 @@ +/* +Copyright 2021 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 versioned + +import ( + "fmt" + + customv1alpha1 "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + CustomV1alpha1() customv1alpha1.CustomV1alpha1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + customV1alpha1 *customv1alpha1.CustomV1alpha1Client +} + +// CustomV1alpha1 retrieves the CustomV1alpha1Client +func (c *Clientset) CustomV1alpha1() customv1alpha1.CustomV1alpha1Interface { + return c.customV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.customV1alpha1, err = customv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.customV1alpha1 = customv1alpha1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.customV1alpha1 = customv1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/cel/pkg/client/clientset/versioned/doc.go b/cel/pkg/client/clientset/versioned/doc.go new file mode 100644 index 000000000..115793bae --- /dev/null +++ b/cel/pkg/client/clientset/versioned/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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. + +// This package has the automatically generated clientset. +package versioned diff --git a/cel/pkg/client/clientset/versioned/fake/clientset_generated.go b/cel/pkg/client/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 000000000..213ddd963 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,82 @@ +/* +Copyright 2021 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 ( + clientset "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned" + customv1alpha1 "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1" + fakecustomv1alpha1 "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +var _ clientset.Interface = &Clientset{} + +// CustomV1alpha1 retrieves the CustomV1alpha1Client +func (c *Clientset) CustomV1alpha1() customv1alpha1.CustomV1alpha1Interface { + return &fakecustomv1alpha1.FakeCustomV1alpha1{Fake: &c.Fake} +} diff --git a/cel/pkg/client/clientset/versioned/fake/doc.go b/cel/pkg/client/clientset/versioned/fake/doc.go new file mode 100644 index 000000000..7f73ec73d --- /dev/null +++ b/cel/pkg/client/clientset/versioned/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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. + +// This package has the automatically generated fake clientset. +package fake diff --git a/cel/pkg/client/clientset/versioned/fake/register.go b/cel/pkg/client/clientset/versioned/fake/register.go new file mode 100644 index 000000000..2da02a7bc --- /dev/null +++ b/cel/pkg/client/clientset/versioned/fake/register.go @@ -0,0 +1,56 @@ +/* +Copyright 2021 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 ( + customv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + customv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/cel/pkg/client/clientset/versioned/scheme/doc.go b/cel/pkg/client/clientset/versioned/scheme/doc.go new file mode 100644 index 000000000..ec818b613 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/scheme/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/cel/pkg/client/clientset/versioned/scheme/register.go b/cel/pkg/client/clientset/versioned/scheme/register.go new file mode 100644 index 000000000..f48ad29dd --- /dev/null +++ b/cel/pkg/client/clientset/versioned/scheme/register.go @@ -0,0 +1,56 @@ +/* +Copyright 2021 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 scheme + +import ( + customv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + customv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel.go b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel.go new file mode 100644 index 000000000..687975e15 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel.go @@ -0,0 +1,178 @@ +/* +Copyright 2021 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 ( + "context" + "time" + + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + scheme "github.com/tektoncd/experimental/cel/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" +) + +// CELsGetter has a method to return a CELInterface. +// A group's client should implement this interface. +type CELsGetter interface { + CELs(namespace string) CELInterface +} + +// CELInterface has methods to work with CEL resources. +type CELInterface interface { + Create(ctx context.Context, cEL *v1alpha1.CEL, opts v1.CreateOptions) (*v1alpha1.CEL, error) + Update(ctx context.Context, cEL *v1alpha1.CEL, opts v1.UpdateOptions) (*v1alpha1.CEL, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.CEL, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.CELList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.CEL, err error) + CELExpansion +} + +// cELs implements CELInterface +type cELs struct { + client rest.Interface + ns string +} + +// newCELs returns a CELs +func newCELs(c *CustomV1alpha1Client, namespace string) *cELs { + return &cELs{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the cEL, and returns the corresponding cEL object, and an error if there is any. +func (c *cELs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.CEL, err error) { + result = &v1alpha1.CEL{} + err = c.client.Get(). + Namespace(c.ns). + Resource("cels"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of CELs that match those selectors. +func (c *cELs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.CELList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.CELList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("cels"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested cELs. +func (c *cELs) Watch(ctx context.Context, 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("cels"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a cEL and creates it. Returns the server's representation of the cEL, and an error, if there is any. +func (c *cELs) Create(ctx context.Context, cEL *v1alpha1.CEL, opts v1.CreateOptions) (result *v1alpha1.CEL, err error) { + result = &v1alpha1.CEL{} + err = c.client.Post(). + Namespace(c.ns). + Resource("cels"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(cEL). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a cEL and updates it. Returns the server's representation of the cEL, and an error, if there is any. +func (c *cELs) Update(ctx context.Context, cEL *v1alpha1.CEL, opts v1.UpdateOptions) (result *v1alpha1.CEL, err error) { + result = &v1alpha1.CEL{} + err = c.client.Put(). + Namespace(c.ns). + Resource("cels"). + Name(cEL.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(cEL). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the cEL and deletes it. Returns an error if one occurs. +func (c *cELs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("cels"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *cELs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("cels"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched cEL. +func (c *cELs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.CEL, err error) { + result = &v1alpha1.CEL{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("cels"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel_client.go b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel_client.go new file mode 100644 index 000000000..b4c53e716 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/cel_client.go @@ -0,0 +1,89 @@ +/* +Copyright 2021 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 ( + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type CustomV1alpha1Interface interface { + RESTClient() rest.Interface + CELsGetter +} + +// CustomV1alpha1Client is used to interact with features provided by the custom.tekton.dev group. +type CustomV1alpha1Client struct { + restClient rest.Interface +} + +func (c *CustomV1alpha1Client) CELs(namespace string) CELInterface { + return newCELs(c, namespace) +} + +// NewForConfig creates a new CustomV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*CustomV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &CustomV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new CustomV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *CustomV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new CustomV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *CustomV1alpha1Client { + return &CustomV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *CustomV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/doc.go b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/doc.go new file mode 100644 index 000000000..530b4b4c9 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/doc.go b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/doc.go new file mode 100644 index 000000000..f363a1ab8 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2021 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 has the automatically generated clients. +package fake diff --git a/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel.go b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel.go new file mode 100644 index 000000000..1f3d38db8 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel.go @@ -0,0 +1,130 @@ +/* +Copyright 2021 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 ( + "context" + + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/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" +) + +// FakeCELs implements CELInterface +type FakeCELs struct { + Fake *FakeCustomV1alpha1 + ns string +} + +var celsResource = schema.GroupVersionResource{Group: "custom.tekton.dev", Version: "v1alpha1", Resource: "cels"} + +var celsKind = schema.GroupVersionKind{Group: "custom.tekton.dev", Version: "v1alpha1", Kind: "CEL"} + +// Get takes name of the cEL, and returns the corresponding cEL object, and an error if there is any. +func (c *FakeCELs) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.CEL, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(celsResource, c.ns, name), &v1alpha1.CEL{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.CEL), err +} + +// List takes label and field selectors, and returns the list of CELs that match those selectors. +func (c *FakeCELs) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.CELList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(celsResource, celsKind, c.ns, opts), &v1alpha1.CELList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.CELList{ListMeta: obj.(*v1alpha1.CELList).ListMeta} + for _, item := range obj.(*v1alpha1.CELList).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 cELs. +func (c *FakeCELs) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(celsResource, c.ns, opts)) + +} + +// Create takes the representation of a cEL and creates it. Returns the server's representation of the cEL, and an error, if there is any. +func (c *FakeCELs) Create(ctx context.Context, cEL *v1alpha1.CEL, opts v1.CreateOptions) (result *v1alpha1.CEL, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(celsResource, c.ns, cEL), &v1alpha1.CEL{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.CEL), err +} + +// Update takes the representation of a cEL and updates it. Returns the server's representation of the cEL, and an error, if there is any. +func (c *FakeCELs) Update(ctx context.Context, cEL *v1alpha1.CEL, opts v1.UpdateOptions) (result *v1alpha1.CEL, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(celsResource, c.ns, cEL), &v1alpha1.CEL{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.CEL), err +} + +// Delete takes name of the cEL and deletes it. Returns an error if one occurs. +func (c *FakeCELs) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(celsResource, c.ns, name), &v1alpha1.CEL{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeCELs) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(celsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.CELList{}) + return err +} + +// Patch applies the patch and returns the patched cEL. +func (c *FakeCELs) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.CEL, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(celsResource, c.ns, name, pt, data, subresources...), &v1alpha1.CEL{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.CEL), err +} diff --git a/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel_client.go b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel_client.go new file mode 100644 index 000000000..500bd462b --- /dev/null +++ b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/fake/fake_cel_client.go @@ -0,0 +1,40 @@ +/* +Copyright 2021 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/experimental/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeCustomV1alpha1 struct { + *testing.Fake +} + +func (c *FakeCustomV1alpha1) CELs(namespace string) v1alpha1.CELInterface { + return &FakeCELs{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeCustomV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/generated_expansion.go b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/generated_expansion.go new file mode 100644 index 000000000..0da2cc0d0 --- /dev/null +++ b/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1/generated_expansion.go @@ -0,0 +1,21 @@ +/* +Copyright 2021 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 + +type CELExpansion interface{} diff --git a/cel/pkg/client/informers/externalversions/cel/interface.go b/cel/pkg/client/informers/externalversions/cel/interface.go new file mode 100644 index 000000000..ca3192102 --- /dev/null +++ b/cel/pkg/client/informers/externalversions/cel/interface.go @@ -0,0 +1,46 @@ +/* +Copyright 2021 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 cel + +import ( + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/cel/v1alpha1" + internalinterfaces "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/cel/pkg/client/informers/externalversions/cel/v1alpha1/cel.go b/cel/pkg/client/informers/externalversions/cel/v1alpha1/cel.go new file mode 100644 index 000000000..f8ad383f2 --- /dev/null +++ b/cel/pkg/client/informers/externalversions/cel/v1alpha1/cel.go @@ -0,0 +1,90 @@ +/* +Copyright 2021 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 ( + "context" + time "time" + + celv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + versioned "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned" + internalinterfaces "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/client/listers/cel/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" +) + +// CELInformer provides access to a shared informer and lister for +// CELs. +type CELInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.CELLister +} + +type cELInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewCELInformer constructs a new informer for CEL 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 NewCELInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredCELInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredCELInformer constructs a new informer for CEL 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 NewFilteredCELInformer(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.CustomV1alpha1().CELs(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.CustomV1alpha1().CELs(namespace).Watch(context.TODO(), options) + }, + }, + &celv1alpha1.CEL{}, + resyncPeriod, + indexers, + ) +} + +func (f *cELInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredCELInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *cELInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&celv1alpha1.CEL{}, f.defaultInformer) +} + +func (f *cELInformer) Lister() v1alpha1.CELLister { + return v1alpha1.NewCELLister(f.Informer().GetIndexer()) +} diff --git a/cel/pkg/client/informers/externalversions/cel/v1alpha1/interface.go b/cel/pkg/client/informers/externalversions/cel/v1alpha1/interface.go new file mode 100644 index 000000000..5226b49d2 --- /dev/null +++ b/cel/pkg/client/informers/externalversions/cel/v1alpha1/interface.go @@ -0,0 +1,45 @@ +/* +Copyright 2021 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 ( + internalinterfaces "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // CELs returns a CELInformer. + CELs() CELInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// CELs returns a CELInformer. +func (v *version) CELs() CELInformer { + return &cELInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/cel/pkg/client/informers/externalversions/factory.go b/cel/pkg/client/informers/externalversions/factory.go new file mode 100644 index 000000000..71d7c45cb --- /dev/null +++ b/cel/pkg/client/informers/externalversions/factory.go @@ -0,0 +1,180 @@ +/* +Copyright 2021 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 externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned" + cel "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/cel" + internalinterfaces "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/internalinterfaces" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + Custom() cel.Interface +} + +func (f *sharedInformerFactory) Custom() cel.Interface { + return cel.New(f, f.namespace, f.tweakListOptions) +} diff --git a/cel/pkg/client/informers/externalversions/generic.go b/cel/pkg/client/informers/externalversions/generic.go new file mode 100644 index 000000000..c22b15a7e --- /dev/null +++ b/cel/pkg/client/informers/externalversions/generic.go @@ -0,0 +1,62 @@ +/* +Copyright 2021 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 externalversions + +import ( + "fmt" + + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=custom.tekton.dev, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("cels"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Custom().V1alpha1().CELs().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/cel/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/cel/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 000000000..d67a471cb --- /dev/null +++ b/cel/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,40 @@ +/* +Copyright 2021 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 internalinterfaces + +import ( + time "time" + + versioned "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/cel/pkg/client/injection/client/client.go b/cel/pkg/client/injection/client/client.go new file mode 100644 index 000000000..932c8349f --- /dev/null +++ b/cel/pkg/client/injection/client/client.go @@ -0,0 +1,57 @@ +/* +Copyright 2021 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 client + +import ( + context "context" + + versioned "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned" + rest "k8s.io/client-go/rest" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterClient(withClient) + injection.Default.RegisterClientFetcher(func(ctx context.Context) interface{} { + return Get(ctx) + }) +} + +// Key is used as the key for associating information with a context.Context. +type Key struct{} + +func withClient(ctx context.Context, cfg *rest.Config) context.Context { + return context.WithValue(ctx, Key{}, versioned.NewForConfigOrDie(cfg)) +} + +// Get extracts the versioned.Interface client from the context. +func Get(ctx context.Context) versioned.Interface { + untyped := ctx.Value(Key{}) + if untyped == nil { + if injection.GetConfig(ctx) == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned.Interface from context. This context is not the application context (which is typically given to constructors via sharedmain).") + } else { + logging.FromContext(ctx).Panic( + "Unable to fetch github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned.Interface from context.") + } + } + return untyped.(versioned.Interface) +} diff --git a/cel/pkg/client/injection/client/fake/fake.go b/cel/pkg/client/injection/client/fake/fake.go new file mode 100644 index 000000000..ea428bdd0 --- /dev/null +++ b/cel/pkg/client/injection/client/fake/fake.go @@ -0,0 +1,57 @@ +/* +Copyright 2021 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/experimental/cel/pkg/client/clientset/versioned/fake" + client "github.com/tektoncd/experimental/cel/pkg/client/injection/client" + runtime "k8s.io/apimachinery/pkg/runtime" + rest "k8s.io/client-go/rest" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Fake.RegisterClient(withClient) + injection.Fake.RegisterClientFetcher(func(ctx context.Context) interface{} { + return Get(ctx) + }) +} + +func withClient(ctx context.Context, cfg *rest.Config) context.Context { + ctx, _ = With(ctx) + return ctx +} + +func With(ctx context.Context, objects ...runtime.Object) (context.Context, *fake.Clientset) { + cs := fake.NewSimpleClientset(objects...) + return context.WithValue(ctx, client.Key{}, cs), cs +} + +// Get extracts the Kubernetes client from the context. +func Get(ctx context.Context) *fake.Clientset { + untyped := ctx.Value(client.Key{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned/fake.Clientset from context.") + } + return untyped.(*fake.Clientset) +} diff --git a/cel/pkg/client/injection/informers/cel/v1alpha1/cel/cel.go b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/cel.go new file mode 100644 index 000000000..979bf3356 --- /dev/null +++ b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/cel.go @@ -0,0 +1,52 @@ +/* +Copyright 2021 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 cel + +import ( + context "context" + + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/cel/v1alpha1" + factory "github.com/tektoncd/experimental/cel/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.Custom().V1alpha1().CELs() + return context.WithValue(ctx, Key{}, inf), inf.Informer() +} + +// Get extracts the typed informer from the context. +func Get(ctx context.Context) v1alpha1.CELInformer { + untyped := ctx.Value(Key{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/cel/v1alpha1.CELInformer from context.") + } + return untyped.(v1alpha1.CELInformer) +} diff --git a/cel/pkg/client/injection/informers/cel/v1alpha1/cel/fake/fake.go b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/fake/fake.go new file mode 100644 index 000000000..c4610929d --- /dev/null +++ b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/fake/fake.go @@ -0,0 +1,40 @@ +/* +Copyright 2021 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" + + cel "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/cel/v1alpha1/cel" + fake "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/factory/fake" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" +) + +var Get = cel.Get + +func init() { + injection.Fake.RegisterInformer(withInformer) +} + +func withInformer(ctx context.Context) (context.Context, controller.Informer) { + f := fake.Get(ctx) + inf := f.Custom().V1alpha1().CELs() + return context.WithValue(ctx, cel.Key{}, inf), inf.Informer() +} diff --git a/cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/cel.go b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/cel.go new file mode 100644 index 000000000..e95a7a7b1 --- /dev/null +++ b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/cel.go @@ -0,0 +1,65 @@ +/* +Copyright 2021 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 filtered + +import ( + context "context" + + v1alpha1 "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/cel/v1alpha1" + filtered "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterFilteredInformers(withInformer) +} + +// Key is used for associating the Informer inside the context.Context. +type Key struct { + Selector string +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := filtered.Get(ctx, selector) + inf := f.Custom().V1alpha1().CELs() + ctx = context.WithValue(ctx, Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} + +// Get extracts the typed informer from the context. +func Get(ctx context.Context, selector string) v1alpha1.CELInformer { + untyped := ctx.Value(Key{Selector: selector}) + if untyped == nil { + logging.FromContext(ctx).Panicf( + "Unable to fetch github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions/cel/v1alpha1.CELInformer with selector %s from context.", selector) + } + return untyped.(v1alpha1.CELInformer) +} diff --git a/cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/fake/fake.go b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/fake/fake.go new file mode 100644 index 000000000..4626476e9 --- /dev/null +++ b/cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered/fake/fake.go @@ -0,0 +1,52 @@ +/* +Copyright 2021 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" + + filtered "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/cel/v1alpha1/cel/filtered" + factoryfiltered "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/factory/filtered" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +var Get = filtered.Get + +func init() { + injection.Fake.RegisterFilteredInformers(withInformer) +} + +func withInformer(ctx context.Context) (context.Context, []controller.Informer) { + untyped := ctx.Value(factoryfiltered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + infs := []controller.Informer{} + for _, selector := range labelSelectors { + f := factoryfiltered.Get(ctx, selector) + inf := f.Custom().V1alpha1().CELs() + ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, inf) + infs = append(infs, inf.Informer()) + } + return ctx, infs +} diff --git a/cel/pkg/client/injection/informers/factory/factory.go b/cel/pkg/client/injection/informers/factory/factory.go new file mode 100644 index 000000000..c4c64bcc9 --- /dev/null +++ b/cel/pkg/client/injection/informers/factory/factory.go @@ -0,0 +1,56 @@ +/* +Copyright 2021 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 factory + +import ( + context "context" + + externalversions "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions" + client "github.com/tektoncd/experimental/cel/pkg/client/injection/client" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterInformerFactory(withInformerFactory) +} + +// Key is used as the key for associating information with a context.Context. +type Key struct{} + +func withInformerFactory(ctx context.Context) context.Context { + c := client.Get(ctx) + opts := make([]externalversions.SharedInformerOption, 0, 1) + if injection.HasNamespaceScope(ctx) { + opts = append(opts, externalversions.WithNamespace(injection.GetNamespaceScope(ctx))) + } + return context.WithValue(ctx, Key{}, + externalversions.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), opts...)) +} + +// Get extracts the InformerFactory from the context. +func Get(ctx context.Context) externalversions.SharedInformerFactory { + untyped := ctx.Value(Key{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions.SharedInformerFactory from context.") + } + return untyped.(externalversions.SharedInformerFactory) +} diff --git a/cel/pkg/client/injection/informers/factory/fake/fake.go b/cel/pkg/client/injection/informers/factory/fake/fake.go new file mode 100644 index 000000000..f499cc8ff --- /dev/null +++ b/cel/pkg/client/injection/informers/factory/fake/fake.go @@ -0,0 +1,45 @@ +/* +Copyright 2021 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" + + externalversions "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions" + fake "github.com/tektoncd/experimental/cel/pkg/client/injection/client/fake" + factory "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/factory" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" +) + +var Get = factory.Get + +func init() { + injection.Fake.RegisterInformerFactory(withInformerFactory) +} + +func withInformerFactory(ctx context.Context) context.Context { + c := fake.Get(ctx) + opts := make([]externalversions.SharedInformerOption, 0, 1) + if injection.HasNamespaceScope(ctx) { + opts = append(opts, externalversions.WithNamespace(injection.GetNamespaceScope(ctx))) + } + return context.WithValue(ctx, factory.Key{}, + externalversions.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), opts...)) +} diff --git a/cel/pkg/client/injection/informers/factory/filtered/fake/fake_filtered_factory.go b/cel/pkg/client/injection/informers/factory/filtered/fake/fake_filtered_factory.go new file mode 100644 index 000000000..954f74bcc --- /dev/null +++ b/cel/pkg/client/injection/informers/factory/filtered/fake/fake_filtered_factory.go @@ -0,0 +1,59 @@ +/* +Copyright 2021 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 fakeFilteredFactory + +import ( + context "context" + + externalversions "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions" + fake "github.com/tektoncd/experimental/cel/pkg/client/injection/client/fake" + filtered "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/factory/filtered" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +var Get = filtered.Get + +func init() { + injection.Fake.RegisterInformerFactory(withInformerFactory) +} + +func withInformerFactory(ctx context.Context) context.Context { + c := fake.Get(ctx) + opts := []externalversions.SharedInformerOption{} + if injection.HasNamespaceScope(ctx) { + opts = append(opts, externalversions.WithNamespace(injection.GetNamespaceScope(ctx))) + } + untyped := ctx.Value(filtered.LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + for _, selector := range labelSelectors { + thisOpts := append(opts, externalversions.WithTweakListOptions(func(l *v1.ListOptions) { + l.LabelSelector = selector + })) + ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, + externalversions.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), thisOpts...)) + } + return ctx +} diff --git a/cel/pkg/client/injection/informers/factory/filtered/filtered_factory.go b/cel/pkg/client/injection/informers/factory/filtered/filtered_factory.go new file mode 100644 index 000000000..54c543257 --- /dev/null +++ b/cel/pkg/client/injection/informers/factory/filtered/filtered_factory.go @@ -0,0 +1,77 @@ +/* +Copyright 2021 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 filteredFactory + +import ( + context "context" + + externalversions "github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions" + client "github.com/tektoncd/experimental/cel/pkg/client/injection/client" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + controller "knative.dev/pkg/controller" + injection "knative.dev/pkg/injection" + logging "knative.dev/pkg/logging" +) + +func init() { + injection.Default.RegisterInformerFactory(withInformerFactory) +} + +// Key is used as the key for associating information with a context.Context. +type Key struct { + Selector string +} + +type LabelKey struct{} + +func WithSelectors(ctx context.Context, selector ...string) context.Context { + return context.WithValue(ctx, LabelKey{}, selector) +} + +func withInformerFactory(ctx context.Context) context.Context { + c := client.Get(ctx) + opts := []externalversions.SharedInformerOption{} + if injection.HasNamespaceScope(ctx) { + opts = append(opts, externalversions.WithNamespace(injection.GetNamespaceScope(ctx))) + } + untyped := ctx.Value(LabelKey{}) + if untyped == nil { + logging.FromContext(ctx).Panic( + "Unable to fetch labelkey from context.") + } + labelSelectors := untyped.([]string) + for _, selector := range labelSelectors { + thisOpts := append(opts, externalversions.WithTweakListOptions(func(l *v1.ListOptions) { + l.LabelSelector = selector + })) + ctx = context.WithValue(ctx, Key{Selector: selector}, + externalversions.NewSharedInformerFactoryWithOptions(c, controller.GetResyncPeriod(ctx), thisOpts...)) + } + return ctx +} + +// Get extracts the InformerFactory from the context. +func Get(ctx context.Context, selector string) externalversions.SharedInformerFactory { + untyped := ctx.Value(Key{Selector: selector}) + if untyped == nil { + logging.FromContext(ctx).Panicf( + "Unable to fetch github.com/tektoncd/experimental/cel/pkg/client/informers/externalversions.SharedInformerFactory with selector %s from context.", selector) + } + return untyped.(externalversions.SharedInformerFactory) +} diff --git a/cel/pkg/client/listers/cel/v1alpha1/cel.go b/cel/pkg/client/listers/cel/v1alpha1/cel.go new file mode 100644 index 000000000..be6009e0a --- /dev/null +++ b/cel/pkg/client/listers/cel/v1alpha1/cel.go @@ -0,0 +1,99 @@ +/* +Copyright 2021 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/experimental/cel/pkg/apis/cel/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// CELLister helps list CELs. +// All objects returned here must be treated as read-only. +type CELLister interface { + // List lists all CELs in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.CEL, err error) + // CELs returns an object that can list and get CELs. + CELs(namespace string) CELNamespaceLister + CELListerExpansion +} + +// cELLister implements the CELLister interface. +type cELLister struct { + indexer cache.Indexer +} + +// NewCELLister returns a new CELLister. +func NewCELLister(indexer cache.Indexer) CELLister { + return &cELLister{indexer: indexer} +} + +// List lists all CELs in the indexer. +func (s *cELLister) List(selector labels.Selector) (ret []*v1alpha1.CEL, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.CEL)) + }) + return ret, err +} + +// CELs returns an object that can list and get CELs. +func (s *cELLister) CELs(namespace string) CELNamespaceLister { + return cELNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// CELNamespaceLister helps list and get CELs. +// All objects returned here must be treated as read-only. +type CELNamespaceLister interface { + // List lists all CELs in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.CEL, err error) + // Get retrieves the CEL from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.CEL, error) + CELNamespaceListerExpansion +} + +// cELNamespaceLister implements the CELNamespaceLister +// interface. +type cELNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all CELs in the indexer for a given namespace. +func (s cELNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.CEL, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.CEL)) + }) + return ret, err +} + +// Get retrieves the CEL from the indexer for a given namespace and name. +func (s cELNamespaceLister) Get(name string) (*v1alpha1.CEL, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("cel"), name) + } + return obj.(*v1alpha1.CEL), nil +} diff --git a/cel/pkg/client/listers/cel/v1alpha1/expansion_generated.go b/cel/pkg/client/listers/cel/v1alpha1/expansion_generated.go new file mode 100644 index 000000000..66df35b02 --- /dev/null +++ b/cel/pkg/client/listers/cel/v1alpha1/expansion_generated.go @@ -0,0 +1,27 @@ +/* +Copyright 2021 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 + +// CELListerExpansion allows custom methods to be added to +// CELLister. +type CELListerExpansion interface{} + +// CELNamespaceListerExpansion allows custom methods to be added to +// CELNamespaceLister. +type CELNamespaceListerExpansion interface{} diff --git a/cel/pkg/reconciler/cel/celrun.go b/cel/pkg/reconciler/cel/celrun.go deleted file mode 100644 index 2d06db79b..000000000 --- a/cel/pkg/reconciler/cel/celrun.go +++ /dev/null @@ -1,162 +0,0 @@ -/* -Copyright 2021 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 cel - -import ( - "context" - "fmt" - "github.com/google/cel-go/cel" - "github.com/google/cel-go/common/types" - "github.com/tektoncd/pipeline/pkg/client/injection/reconciler/pipeline/v1alpha1/run" - "knative.dev/pkg/apis" - "knative.dev/pkg/logging" - - v1alpha1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" - v1 "k8s.io/api/core/v1" - reconciler "knative.dev/pkg/reconciler" -) - -const ( - // ReasonFailedValidation indicates that the reason for failure status is that Run failed runtime validation - ReasonFailedValidation = "RunValidationFailed" - - // ReasonSyntaxError indicates that the reason for failure status is that a CEL expression couldn't be parsed - ReasonSyntaxError = "SyntaxError" - - // ReasonEvaluationError indicates that the reason for failure status is that a CEL expression couldn't be evaluated - // typically due to evaluation environment or executable program - ReasonEvaluationError = "EvaluationError" - - // ReasonEvaluationSuccess indicates that the reason for the success status is that all CEL expressions were - // evaluated successfully and the results were produced - ReasonEvaluationSuccess = "EvaluationSuccess" -) - -// 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 { -} - -// Check that our Reconciler implements Interface -var _ run.Interface = (*Reconciler)(nil) - -// ReconcileKind implements Interface.ReconcileKind. -func (r *Reconciler) ReconcileKind(ctx context.Context, run *v1alpha1.Run) reconciler.Event { - logger := logging.FromContext(ctx) - logger.Infof("Reconciling Run %s/%s", run.Namespace, run.Name) - - // If the Run has not started, initialize the Condition and set the start time. - if !run.HasStarted() { - logger.Infof("Starting new Run %s/%s", run.Namespace, run.Name) - run.Status.InitializeConditions() - // In case node time was not synchronized, when controller has been scheduled to other nodes. - if run.Status.StartTime.Sub(run.CreationTimestamp.Time) < 0 { - logger.Warnf("Run %s/%s createTimestamp %s is after the Run started %s", run.Namespace, run.Name, run.CreationTimestamp, run.Status.StartTime) - run.Status.StartTime = &run.CreationTimestamp - } - } - - if run.IsDone() { - logger.Infof("Run %s/%s is done", run.Namespace, run.Name) - return nil - } - - if err := validate(run); err != nil { - logger.Errorf("Run %s/%s is invalid because of %s", run.Namespace, run.Name, err) - run.Status.MarkRunFailed(ReasonFailedValidation, - "Run can't be run because it has an invalid spec - %v", err) - return nil - } - - // Create a program environment configured with the standard library of CEL functions and macros - env, err := cel.NewEnv(cel.Declarations()) - if err != nil { - logger.Errorf("Couldn't create a program env with standard library of CEL functions & macros when reconciling Run %s/%s: %v", run.Namespace, run.Name, err) - return err - } - - var runResults []v1alpha1.RunResult - for _, param := range run.Spec.Params { - // Combine the Parse and Check phases CEL program compilation to produce an Ast and associated issues - ast, iss := env.Compile(param.Value.StringVal) - if iss.Err() != nil { - logger.Errorf("CEL expression %s could not be parsed when reconciling Run %s/%s: %v", param.Name, run.Namespace, run.Name, iss.Err()) - run.Status.MarkRunFailed(ReasonSyntaxError, - "CEL expression %s could not be parsed", param.Name, iss.Err()) - return nil - } - - // Generate an evaluable instance of the Ast within the environment - prg, err := env.Program(ast) - if err != nil { - logger.Errorf("CEL expression %s could not be evaluated when reconciling Run %s/%s: %v", param.Name, run.Namespace, run.Name, err) - run.Status.MarkRunFailed(ReasonEvaluationError, - "CEL expression %s could not be evaluated", param.Name, err) - return nil - } - - // Evaluate the CEL expression (Ast) - out, _, err := prg.Eval(map[string]interface{}{}) - if err != nil { - logger.Errorf("CEL expression %s could not be evaluated when reconciling Run %s/%s: %v", param.Name, run.Namespace, run.Name, err) - run.Status.MarkRunFailed(ReasonEvaluationError, - "CEL expression %s could not be evaluated", param.Name, err) - return nil - } - - // Evaluation of CEL expression was successful - logger.Infof("CEL expression %s evaluated successfully when reconciling Run %s/%s", param.Name, run.Namespace, run.Name) - runResults = append(runResults, v1alpha1.RunResult{ - Name: param.Name, - Value: fmt.Sprintf("%s", out.ConvertToType(types.StringType).Value()), - }) - } - - // All CEL expressions were evaluated successfully - run.Status.Results = append(run.Status.Results, runResults...) - run.Status.MarkRunSucceeded(ReasonEvaluationSuccess, - "CEL expressions were evaluated successfully") - - return newReconciledNormal(run.Namespace, run.Name) -} - -func validate(run *v1alpha1.Run) (errs *apis.FieldError) { - errs = errs.Also(validateExpressionsProvided(run)) - errs = errs.Also(validateExpressionsType(run)) - return errs -} - -func validateExpressionsProvided(run *v1alpha1.Run) (errs *apis.FieldError) { - if len(run.Spec.Params) == 0 { - errs = errs.Also(apis.ErrMissingField("params")) - } - return errs -} - -func validateExpressionsType(run *v1alpha1.Run) (errs *apis.FieldError) { - for _, param := range run.Spec.Params { - if param.Value.StringVal == "" { - errs = errs.Also(apis.ErrInvalidValue(fmt.Sprintf("CEL expression parameter %s must be a string", param.Name), - "value").ViaFieldKey("params", param.Name)) - } - } - return errs -} diff --git a/cel/pkg/reconciler/cel/celrun_test.go b/cel/pkg/reconciler/cel/celrun_test.go deleted file mode 100644 index 6ffa075ea..000000000 --- a/cel/pkg/reconciler/cel/celrun_test.go +++ /dev/null @@ -1,302 +0,0 @@ -/* -Copyright 2021 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 cel - -import ( - "context" - "fmt" - "github.com/google/go-cmp/cmp" - "github.com/tektoncd/experimental/cel/test" - "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" - "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" - ttesting "github.com/tektoncd/pipeline/pkg/reconciler/testing" - "github.com/tektoncd/pipeline/test/diff" - - "github.com/tektoncd/pipeline/test/names" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/tools/record" - "knative.dev/pkg/apis" - "knative.dev/pkg/configmap" - "knative.dev/pkg/controller" - "knative.dev/pkg/logging" - "knative.dev/pkg/reconciler" - "strings" - "testing" - "time" -) - -func TestReconcileCelRun(t *testing.T) { - testcases := []struct { - name string - run *v1alpha1.Run - expectedStatus corev1.ConditionStatus - expectedReason string - expectedResults []v1alpha1.RunResult - expectedMessage string - expectedEvents []string - }{{ - name: "one expression successful", - run: &v1alpha1.Run{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cel-run", - Namespace: "foo", - Labels: map[string]string{ - "myTestLabel": "myTestLabelValue", - }, - Annotations: map[string]string{ - "myTestAnnotation": "myTestAnnotationValue", - }, - }, - Spec: v1alpha1.RunSpec{ - Params: []v1beta1.Param{{ - Name: "expr1", - Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "type(100)"}, - }}, - Ref: &v1alpha1.TaskRef{ - APIVersion: apiVersion, - Kind: kind, - Name: "a-celrun", - }, - }, - }, - expectedStatus: corev1.ConditionTrue, - expectedReason: ReasonEvaluationSuccess, - expectedMessage: "CEL expressions were evaluated successfully", - expectedResults: []v1alpha1.RunResult{{ - Name: "expr1", - Value: "int", - }}, - expectedEvents: []string{"Normal RunReconciled Run reconciled: \"foo/cel-run\""}, - }, { - name: "multiple expressions successful", - run: &v1alpha1.Run{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cel-run", - Namespace: "foo", - Labels: map[string]string{ - "myTestLabel": "myTestLabelValue", - }, - Annotations: map[string]string{ - "myTestAnnotation": "myTestAnnotationValue", - }, - }, - Spec: v1alpha1.RunSpec{ - Params: []v1beta1.Param{{ - Name: "expr1", - Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "type(100)"}, - }, { - Name: "expr2", - Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "3 == 3"}, - }}, - Ref: &v1alpha1.TaskRef{ - APIVersion: apiVersion, - Kind: kind, - Name: "a-celrun", - }, - }, - }, - expectedStatus: corev1.ConditionTrue, - expectedReason: ReasonEvaluationSuccess, - expectedMessage: "CEL expressions were evaluated successfully", - expectedResults: []v1alpha1.RunResult{{ - Name: "expr1", - Value: "int", - }, { - Name: "expr2", - Value: "true", - }}, - expectedEvents: []string{"Normal RunReconciled Run reconciled: \"foo/cel-run\""}, - }, { - name: "CEL expressions with invalid type", - run: &v1alpha1.Run{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cel-run", - Namespace: "foo", - Labels: map[string]string{ - "myTestLabel": "myTestLabelValue", - }, - Annotations: map[string]string{ - "myTestAnnotation": "myTestAnnotationValue", - }, - }, - Spec: v1alpha1.RunSpec{ - Params: []v1beta1.Param{{ - Name: "expr1", - Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeArray, ArrayVal: []string{"type(100)", "3 == 3"}}, - }}, - Ref: &v1alpha1.TaskRef{ - APIVersion: apiVersion, - Kind: kind, - Name: "a-celrun", - }, - }, - }, - expectedStatus: corev1.ConditionFalse, - expectedReason: ReasonFailedValidation, - expectedMessage: "Run can't be run because it has an invalid spec - invalid value: CEL expression parameter expr1 must be a string: params[expr1].value", - }, { - name: "missing CEL expressions", - run: &v1alpha1.Run{ - ObjectMeta: metav1.ObjectMeta{ - Name: "cel-run", - Namespace: "foo", - Labels: map[string]string{ - "myTestLabel": "myTestLabelValue", - }, - Annotations: map[string]string{ - "myTestAnnotation": "myTestAnnotationValue", - }, - }, - Spec: v1alpha1.RunSpec{ - Ref: &v1alpha1.TaskRef{ - APIVersion: apiVersion, - Kind: kind, - Name: "a-celrun", - }, - }, - }, - expectedStatus: corev1.ConditionFalse, - expectedReason: ReasonFailedValidation, - expectedMessage: "Run can't be run because it has an invalid spec - missing field(s): params", - }} - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - ctx := context.Background() - names.TestingSeed() - - d := test.Data{ - Runs: []*v1alpha1.Run{tc.run}, - } - - testAssets, _ := getCelController(t, d) - c := testAssets.Controller - clients := testAssets.Clients - - if err := c.Reconciler.Reconcile(ctx, getRunName(tc.run)); err != nil { - t.Fatalf("Error reconciling: %s", err) - } - - // Fetch the updated Run - reconciledRun, err := clients.Pipeline.TektonV1alpha1().Runs(tc.run.Namespace).Get(ctx, tc.run.Name, metav1.GetOptions{}) - if err != nil { - t.Fatalf("Error getting reconciled run from fake client: %s", err) - } - - // Verify that the Run has the expected status and reason - checkRunCondition(t, reconciledRun, tc.expectedStatus, tc.expectedReason, tc.expectedMessage) - - // Verify expected events were created - if err := checkEvents(testAssets.Recorder, tc.name, tc.expectedEvents); err != nil { - t.Errorf(err.Error()) - } - - // Verify the expected Results were produced - if d := cmp.Diff(tc.expectedResults, reconciledRun.Status.Results); d != "" { - t.Errorf("Status Results: %s", diff.PrintWantGot(d)) - } - - }) - } -} - -func getCelController(t *testing.T, d test.Data) (test.Assets, func()) { - ctx, _ := ttesting.SetupFakeContext(t) - ctx, cancel := context.WithCancel(ctx) - c, informers := test.SeedTestData(t, ctx, d) - - configMapWatcher := configmap.NewStaticWatcher() - //configMapWatcher := configmap.NewInformedWatcher(c.Kube, system.GetNamespace()) - ctl := NewController(ctx, configMapWatcher) - - if la, ok := ctl.Reconciler.(reconciler.LeaderAware); ok { - la.Promote(reconciler.UniversalBucket(), func(reconciler.Bucket, types.NamespacedName) {}) - } - if err := configMapWatcher.Start(ctx.Done()); err != nil { - t.Fatalf("error starting configmap watcher: %v", err) - } - - return test.Assets{ - Logger: logging.FromContext(ctx), - Controller: ctl, - Clients: c, - Informers: informers, - Recorder: controller.GetEventRecorder(ctx).(*record.FakeRecorder), - }, cancel -} - -func getRunName(run *v1alpha1.Run) string { - return strings.Join([]string{run.Namespace, run.Name}, "/") -} - -func checkRunCondition(t *testing.T, run *v1alpha1.Run, expectedStatus corev1.ConditionStatus, expectedReason string, expectedMessage string) { - condition := run.Status.GetCondition(apis.ConditionSucceeded) - if condition == nil { - t.Error("Condition missing in Run") - } else { - if condition.Status != expectedStatus { - t.Errorf("Expected Run status to be %v but was %v", expectedStatus, condition) - } - if condition.Reason != expectedReason { - t.Errorf("Expected reason to be %q but was %q", expectedReason, condition.Reason) - } - if condition.Message != expectedMessage { - t.Errorf("Expected message to be %q but was %q", expectedMessage, condition.Message) - } - } - if run.Status.StartTime == nil { - t.Errorf("Expected Run start time to be set but it wasn't") - } - if expectedStatus == corev1.ConditionUnknown { - if run.Status.CompletionTime != nil { - t.Errorf("Expected Run completion time to not be set but it was") - } - } else if run.Status.CompletionTime == nil { - t.Errorf("Expected Run completion time to be set but it wasn't") - } -} - -func checkEvents(fr *record.FakeRecorder, testName string, wantEvents []string) error { - // The fake recorder runs in a go routine, so the timeout is here to avoid waiting - // on the channel forever if fewer than expected events are received. - // We only hit the timeout in case of failure of the test, so the actual value - // of the timeout is not so relevant. It's only used when tests are going to fail. - timer := time.NewTimer(1 * time.Second) - foundEvents := []string{} - for ii := 0; ii < len(wantEvents)+1; ii++ { - // We loop over all the events that we expect. Once they are all received - // we exit the loop. If we never receive enough events, the timeout takes us - // out of the loop. - select { - case event := <-fr.Events: - foundEvents = append(foundEvents, event) - if ii > len(wantEvents)-1 { - return fmt.Errorf(`Received extra event "%s" for test "%s"`, event, testName) - } - wantEvent := wantEvents[ii] - if !(strings.HasPrefix(event, wantEvent)) { - return fmt.Errorf(`Expected event "%s" but got "%s" instead for test "%s"`, wantEvent, event, testName) - } - case <-timer.C: - if len(foundEvents) > len(wantEvents) { - return fmt.Errorf(`Received %d events but %d expected for test "%s". Found events: %#v`, len(foundEvents), len(wantEvents), testName, foundEvents) - } - } - } - return nil -} diff --git a/cel/pkg/reconciler/cel/controller.go b/cel/pkg/reconciler/cel/controller.go deleted file mode 100644 index 02b35f8ce..000000000 --- a/cel/pkg/reconciler/cel/controller.go +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2021 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 cel - -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" - tkncontroller "github.com/tektoncd/pipeline/pkg/controller" - "k8s.io/client-go/tools/cache" - configmap "knative.dev/pkg/configmap" - controller "knative.dev/pkg/controller" - logging "knative.dev/pkg/logging" -) - -const ( - ControllerName = "cel-controller" - apiVersion = "cel.tekton.dev/v1alpha1" - kind = "CEL" -) - -// 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) - - r := &Reconciler{} - - impl := v1alpha1run.NewImpl(ctx, r, func(impl *controller.Impl) controller.Options { - return controller.Options{ - AgentName: ControllerName, - } - }) - - logger.Info("Setting up event handlers") - - runInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ - FilterFunc: tkncontroller.FilterRunRef(apiVersion, kind), - Handler: controller.HandleAll(impl.Enqueue), - }) - - return impl -} diff --git a/cel/pkg/reconciler/celrun/celrun.go b/cel/pkg/reconciler/celrun/celrun.go new file mode 100644 index 000000000..0dfb59c64 --- /dev/null +++ b/cel/pkg/reconciler/celrun/celrun.go @@ -0,0 +1,280 @@ +/* +Copyright 2021 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 celrun + +import ( + "context" + "encoding/json" + "fmt" + gocel "github.com/google/cel-go/cel" + "github.com/google/cel-go/checker/decls" + celtypes "github.com/google/cel-go/common/types" + "github.com/hashicorp/go-multierror" + "github.com/tektoncd/experimental/cel/pkg/apis/cel" + celv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + celclientset "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned" + listerscel "github.com/tektoncd/experimental/cel/pkg/client/listers/cel/v1alpha1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + clientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" + "github.com/tektoncd/pipeline/pkg/client/injection/reconciler/pipeline/v1alpha1/run" + listersalpha "github.com/tektoncd/pipeline/pkg/client/listers/pipeline/v1alpha1" + "github.com/tektoncd/pipeline/pkg/reconciler/events" + "go.uber.org/zap" + "google.golang.org/genproto/googleapis/api/expr/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "knative.dev/pkg/apis" + "knative.dev/pkg/logging" + "knative.dev/pkg/reconciler" + "reflect" +) + +const ( + // CELLabelKey is the label identifier for a CEL, which is added to the Run + CELLabelKey = "/CEL" + + // KindLabelKey is the label identifier for the Kind, which is added to the Run + KindLabelKey = "kind" +) + +// Reconciler implements controller.Reconciler for Run resources. +type Reconciler struct { + pipelineClientSet clientset.Interface + CELClientSet celclientset.Interface + runLister listersalpha.RunLister + CELLister listerscel.CELLister +} + +// Check that our Reconciler implements Interface +var _ run.Interface = (*Reconciler)(nil) + +// ReconcileKind implements Interface.ReconcileKind. +func (r *Reconciler) ReconcileKind(ctx context.Context, run *v1alpha1.Run) reconciler.Event { + var merr error + logger := logging.FromContext(ctx) + logger.With(zap.String("Run", fmt.Sprintf("%s/%s", run.Namespace, run.Name))) + logger.Infof("Reconciling Run") + + if !run.HasStarted() { + logger.Infof("Starting new Run") + run.Status.InitializeConditions() + // In case node time was not synchronized, when controller has been scheduled to other nodes. + if run.Status.StartTime.Sub(run.CreationTimestamp.Time) < 0 { + logger.Warnf("Run createTimestamp %s is after the Run started %s", run.CreationTimestamp, run.Status.StartTime) + run.Status.StartTime = &run.CreationTimestamp + } + afterCondition := run.Status.GetCondition(apis.ConditionSucceeded) + events.Emit(ctx, nil, afterCondition, run) + } + + if run.IsDone() { + logger.Infof("Run is done") + return nil + } + + beforeCondition := run.Status.GetCondition(apis.ConditionSucceeded) + + status := &celv1alpha1.CELStatus{} + if err := run.Status.DecodeExtraFields(status); err != nil { + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonInternalError.String(), + "Internal error calling DecodeExtraFields: %v", err) + logger.Errorf("DecodeExtraFields error: %v", err.Error()) + } + + if err := r.reconcile(ctx, run, status); err != nil { + logger.Errorf("Reconcile error: %v", err.Error()) + merr = multierror.Append(merr, err) + } + + if err := r.updateLabelsAndAnnotations(ctx, run); err != nil { + logger.Warn("Failed to update Run labels/annotations", zap.Error(err)) + merr = multierror.Append(merr, err) + } + + if err := run.Status.EncodeExtraFields(status); err != nil { + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonCouldntGetCEL.String(), + "Internal error calling EncodeExtraFields: %v", err) + logger.Errorf("EncodeExtraFields error: %v", err.Error()) + } + + afterCondition := run.Status.GetCondition(apis.ConditionSucceeded) + events.Emit(ctx, beforeCondition, afterCondition, run) + + // Only transient errors that should retry the reconcile are returned. + return merr +} + +func (c *Reconciler) reconcile(ctx context.Context, run *v1alpha1.Run, status *celv1alpha1.CELStatus) error { + logger := logging.FromContext(ctx) + + CELMeta, CELSpec, err := c.getCEL(ctx, run) + if err != nil { + return nil + } + + storeCELSpec(status, CELSpec) + + propagateCELLabelsAndAnnotations(run, CELMeta) + + if err := CELSpec.Validate(); err != nil { + logger.Errorf("Run is invalid because of %s", err) + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonFailedValidation.String(), + "Run can't be run because it has an invalid spec - %v", err) + return nil + } + + variablesMap := getVariablesMap(CELSpec.Variables) + // Create a program environment configured with the standard library of CEL functions and macros + env, err := gocel.NewEnv(gocel.Declarations(getCELEnvironmentDeclarations(variablesMap)...)) + if err != nil { + logger.Errorf("Couldn't create a program env with standard library of CEL functions & macros when reconciling Run: %v", err) + return err + } + + for _, expression := range CELSpec.Expressions { + // Combine the Parse and Check phases CEL program compilation to produce an Ast and associated issues + ast, iss := env.Compile(expression.Value.StringVal) + if iss.Err() != nil { + logger.Errorf("CEL expression %s could not be parsed when reconciling Run: %v", expression.Name, iss.Err()) + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonSyntaxError.String(), + "CEL expression %s could not be parsed", expression.Name, iss.Err()) + return nil + } + + // Generate an evaluable instance of the Ast within the environment + prg, err := env.Program(ast) + if err != nil { + logger.Errorf("CEL expression %s could not be evaluated when reconciling Run: %v", expression.Name, err) + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonEvaluationError.String(), + "CEL expression %s could not be evaluated", expression.Name, err) + return nil + } + + // Evaluate the CEL expression (Ast) + variablesMap := getVariablesMap(CELSpec.Variables) + out, _, err := prg.Eval(variablesMap) + if err != nil { + logger.Errorf("CEL expression %s could not be evaluated when reconciling Run: %v", expression.Name, err) + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonEvaluationError.String(), + "CEL expression %s could not be evaluated", expression.Name, err) + return nil + } + + // Evaluation of CEL expression was successful + logger.Infof("CEL expression %s evaluated successfully when reconciling Run", expression.Name) + status.Results = append(status.Results, v1alpha1.RunResult{ + Name: expression.Name, + Value: fmt.Sprintf("%s", out.ConvertToType(celtypes.StringType).Value()), + }) + } + + // All CEL expressions were evaluated successfully + run.Status.Results = append(run.Status.Results, status.Results...) + run.Status.MarkRunSucceeded(celv1alpha1.CELRunReasonEvaluationSuccess.String(), + "CEL expressions were evaluated successfully") + + return nil +} + +func (c *Reconciler) getCEL(ctx context.Context, run *v1alpha1.Run) (*metav1.ObjectMeta, *celv1alpha1.CELSpec, error) { + if run.Spec.Ref == nil || run.Spec.Ref.Name == "" { + // Run does not require name but for CEL it does + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonCouldntGetCEL.String(), + "Missing spec.ref.name for Run %s/%s", + run.Namespace, run.Name) + return nil, nil, fmt.Errorf("missing spec.ref.name for Run %s", fmt.Sprintf("%s/%s", run.Namespace, run.Name)) + } + // Use the k8s client to get the CEL rather than the lister. This avoids a timing issue where + // the CEL is not yet in the lister cache if it is created at nearly the same time as the Run. + // See https://github.com/tektoncd/pipeline/issues/2740 for discussion on this issue. + cs, err := c.CELClientSet.CustomV1alpha1().CELs(run.Namespace).Get(ctx, run.Spec.Ref.Name, metav1.GetOptions{}) + if err != nil { + run.Status.MarkRunFailed(celv1alpha1.CELRunReasonCouldntGetCEL.String(), + "Error retrieving CEL for Run %s/%s: %s", + run.Namespace, run.Name, err) + return nil, nil, fmt.Errorf("error retrieving CEL for Run %s: %w", fmt.Sprintf("%s/%s", run.Namespace, run.Name), err) + } + + return &cs.ObjectMeta, &cs.Spec, nil +} + +func storeCELSpec(status *celv1alpha1.CELStatus, cs *celv1alpha1.CELSpec) { + // Only store the CELSpec once, if it has never been set before + if status.Spec == nil { + status.Spec = cs + } +} + +func propagateCELLabelsAndAnnotations(run *v1alpha1.Run, CELMeta *metav1.ObjectMeta) { + // Propagate labels from CEL to Run + if run.ObjectMeta.Labels == nil { + run.ObjectMeta.Labels = make(map[string]string, len(CELMeta.Labels)+1) + } + for key, value := range CELMeta.Labels { + run.ObjectMeta.Labels[key] = value + } + run.ObjectMeta.Labels[cel.GroupName+CELLabelKey] = CELMeta.Name + run.ObjectMeta.Labels[KindLabelKey] = cel.ControllerName + + // Propagate annotations from CEL to Run + if run.ObjectMeta.Annotations == nil { + run.ObjectMeta.Annotations = make(map[string]string, len(CELMeta.Annotations)) + } + for key, value := range CELMeta.Annotations { + run.ObjectMeta.Annotations[key] = value + } +} + +func (r *Reconciler) updateLabelsAndAnnotations(ctx context.Context, run *v1alpha1.Run) error { + newRun, err := r.runLister.Runs(run.Namespace).Get(run.Name) + if err != nil { + return fmt.Errorf("error getting Run %s when updating labels/annotations: %w", run.Name, err) + } + if reflect.DeepEqual(run.ObjectMeta.Labels, newRun.ObjectMeta.Labels) && reflect.DeepEqual(run.ObjectMeta.Annotations, newRun.ObjectMeta.Annotations) { + return nil + } + + mergePatch := map[string]interface{}{ + "metadata": map[string]interface{}{ + "labels": run.ObjectMeta.Labels, + "annotations": run.ObjectMeta.Annotations, + }, + } + patch, err := json.Marshal(mergePatch) + if err != nil { + return err + } + _, err = r.pipelineClientSet.TektonV1alpha1().Runs(run.Namespace).Patch(ctx, run.Name, types.MergePatchType, patch, metav1.PatchOptions{}) + return err +} + +func getVariablesMap(variables []*v1beta1.Param) map[string]interface{} { + variablesMap := make(map[string]interface{}) + for _, variable := range variables { + variablesMap[variable.Name] = variable.Value.StringVal + } + return variablesMap +} + +func getCELEnvironmentDeclarations(variablesMap map[string]interface{}) []*expr.Decl { + var CELEnvironmentDeclarations []*expr.Decl + for variableName := range variablesMap { + CELEnvironmentDeclarations = append(CELEnvironmentDeclarations, decls.NewVar(variableName, decls.String)) + } + return CELEnvironmentDeclarations +} diff --git a/cel/pkg/reconciler/celrun/celrun_test.go b/cel/pkg/reconciler/celrun/celrun_test.go new file mode 100644 index 000000000..b50eeb619 --- /dev/null +++ b/cel/pkg/reconciler/celrun/celrun_test.go @@ -0,0 +1,452 @@ +/* +Copyright 2021 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 celrun + +import ( + "context" + "fmt" + "github.com/google/go-cmp/cmp" + "github.com/tektoncd/experimental/cel/pkg/apis/cel" + celv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + fakeclient "github.com/tektoncd/experimental/cel/pkg/client/injection/client/fake" + fakecelinformer "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/cel/v1alpha1/cel/fake" + "github.com/tektoncd/experimental/cel/test" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + ttesting "github.com/tektoncd/pipeline/pkg/reconciler/testing" + "github.com/tektoncd/pipeline/test/diff" + cminformer "knative.dev/pkg/configmap/informer" + + "github.com/tektoncd/pipeline/test/names" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + "knative.dev/pkg/apis" + "knative.dev/pkg/controller" + "knative.dev/pkg/logging" + "knative.dev/pkg/reconciler" + "knative.dev/pkg/system" + _ "knative.dev/pkg/system/testing" + "strings" + "testing" + "time" +) + +var ( + namespace = "" +) + +func TestReconcileCelRun(t *testing.T) { + testcases := []struct { + name string + cel *celv1alpha1.CEL + run *v1alpha1.Run + expectedStatus corev1.ConditionStatus + expectedReason string + expectedResults []v1alpha1.RunResult + expectedMessage string + expectedEvents []string + }{{ + name: "one expression successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "type(100)"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "int", + }}, + expectedEvents: []string{ + "Normal Started", + "Normal Succeeded CEL expressions were evaluated successfully", + }, + }, { + name: "multiple expressions successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "type(100)"}, + }, { + Name: "expr2", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "3 == 3"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "int", + }, { + Name: "expr2", + Value: "true", + }}, + expectedEvents: []string{ + "Normal Started", + "Normal Succeeded CEL expressions were evaluated successfully", + }, + }, { + name: "one expression and one variable successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Variables: []*v1beta1.Param{{ + Name: "var1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "foo"}, + }}, + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "var1 in ['foo', 'bar']"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "true", + }}, + expectedEvents: []string{ + "Normal Started", + "Normal Succeeded CEL expressions were evaluated successfully", + }, + }, { + name: "multiple expressions and multiple variable successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Variables: []*v1beta1.Param{{ + Name: "var1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "foo"}, + }, { + Name: "var2", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "bar"}, + }}, + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "'foo' in [var1, var2]"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "true", + }}, + expectedEvents: []string{ + "Normal Started", + "Normal Succeeded CEL expressions were evaluated successfully", + }, + }, { + name: "CEL expressions with invalid type", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeArray, ArrayVal: []string{"type(100)", "3 == 3"}}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionFalse, + expectedReason: celv1alpha1.CELRunReasonFailedValidation.String(), + expectedMessage: "Run can't be run because it has an invalid spec - invalid value: CEL expression expr1 must be a string: expressions[expr1].value", + expectedEvents: []string{ + "Normal Started", + "Warning Failed Run can't be run because it has an invalid spec - invalid value: CEL expression expr1 must be a string: expressions[expr1].value", + }, + }, { + name: "missing CEL expressions", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionFalse, + expectedReason: celv1alpha1.CELRunReasonFailedValidation.String(), + expectedMessage: "Run can't be run because it has an invalid spec - missing field(s): expressions", + expectedEvents: []string{ + "Normal Started", + "Warning Failed Run can't be run because it has an invalid spec - missing field(s): expressions", + }, + }} + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + ctx := context.Background() + names.TestingSeed() + + d := test.Data{ + Runs: []*v1alpha1.Run{tc.run}, + } + + testAssets, _ := getCELController(t, d, []*celv1alpha1.CEL{tc.cel}) + c := testAssets.Controller + clients := testAssets.Clients + + if err := c.Reconciler.Reconcile(ctx, getRunName(tc.run)); err != nil { + t.Fatalf("Error reconciling: %s", err) + } + + // Fetch the updated Run + reconciledRun, err := clients.Pipeline.TektonV1alpha1().Runs(tc.run.Namespace).Get(ctx, tc.run.Name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("Error getting reconciled run from fake client: %s", err) + } + + // Verify that the Run has the expected status and reason + checkRunCondition(t, reconciledRun, tc.expectedStatus, tc.expectedReason, tc.expectedMessage) + + // Verify expected events were created + if err := checkEvents(testAssets.Recorder, tc.name, tc.expectedEvents); err != nil { + t.Errorf(err.Error()) + } + + // Verify the expected Results were produced + if d := cmp.Diff(tc.expectedResults, reconciledRun.Status.Results); d != "" { + t.Errorf("Status Results: %s", diff.PrintWantGot(d)) + } + + }) + } +} + +func getCELController(t *testing.T, d test.Data, cels []*celv1alpha1.CEL) (test.Assets, func()) { + ctx, _ := ttesting.SetupFakeContext(t) + ctx, cancel := context.WithCancel(ctx) + c, informers := test.SeedTestData(t, ctx, d) + + client := fakeclient.Get(ctx) + client.PrependReactor("*", "cels", test.AddToInformer(t, fakecelinformer.Get(ctx).Informer().GetIndexer())) + for _, cel := range cels { + cel := cel.DeepCopy() // Avoid assumptions that the informer's copy is modified. + if _, err := client.CustomV1alpha1().CELs(cel.Namespace).Create(ctx, cel, metav1.CreateOptions{}); err != nil { + t.Fatal(err) + } + } + + configMapWatcher := cminformer.NewInformedWatcher(c.Kube, system.Namespace()) + ctl := NewController(namespace)(ctx, configMapWatcher) + + if la, ok := ctl.Reconciler.(reconciler.LeaderAware); ok { + la.Promote(reconciler.UniversalBucket(), func(reconciler.Bucket, types.NamespacedName) {}) + } + if err := configMapWatcher.Start(ctx.Done()); err != nil { + t.Fatalf("error starting configmap watcher: %v", err) + } + + return test.Assets{ + Logger: logging.FromContext(ctx), + Controller: ctl, + Clients: c, + Informers: informers, + Recorder: controller.GetEventRecorder(ctx).(*record.FakeRecorder), + }, cancel +} + +func getRunName(run *v1alpha1.Run) string { + return strings.Join([]string{run.Namespace, run.Name}, "/") +} + +func checkRunCondition(t *testing.T, run *v1alpha1.Run, expectedStatus corev1.ConditionStatus, expectedReason string, expectedMessage string) { + condition := run.Status.GetCondition(apis.ConditionSucceeded) + if condition == nil { + t.Error("Condition missing in Run") + } else { + if condition.Status != expectedStatus { + t.Errorf("Expected Run status to be %v but was %v", expectedStatus, condition) + } + if condition.Reason != expectedReason { + t.Errorf("Expected reason to be %q but was %q", expectedReason, condition.Reason) + } + if condition.Message != expectedMessage { + t.Errorf("Expected message to be %q but was %q", expectedMessage, condition.Message) + } + } + if run.Status.StartTime == nil { + t.Errorf("Expected Run start time to be set but it wasn't") + } + if expectedStatus == corev1.ConditionUnknown { + if run.Status.CompletionTime != nil { + t.Errorf("Expected Run completion time to not be set but it was") + } + } else if run.Status.CompletionTime == nil { + t.Errorf("Expected Run completion time to be set but it wasn't") + } +} + +func checkEvents(fr *record.FakeRecorder, testName string, wantEvents []string) error { + // The fake recorder runs in a go routine, so the timeout is here to avoid waiting + // on the channel forever if fewer than expected events are received. + // We only hit the timeout in case of failure of the test, so the actual value + // of the timeout is not so relevant. It's only used when tests are going to fail. + timer := time.NewTimer(1 * time.Second) + foundEvents := []string{} + for ii := 0; ii < len(wantEvents)+1; ii++ { + // We loop over all the events that we expect. Once they are all received + // we exit the loop. If we never receive enough events, the timeout takes us + // out of the loop. + select { + case event := <-fr.Events: + foundEvents = append(foundEvents, event) + if ii > len(wantEvents)-1 { + return fmt.Errorf(`Received extra event "%s" for test "%s"`, event, testName) + } + wantEvent := wantEvents[ii] + if !(strings.HasPrefix(event, wantEvent)) { + return fmt.Errorf(`Expected event "%s" but got "%s" instead for test "%s"`, wantEvent, event, testName) + } + case <-timer.C: + if len(foundEvents) > len(wantEvents) { + return fmt.Errorf(`Received %d events but %d expected for test "%s". Found events: %#v`, len(foundEvents), len(wantEvents), testName, foundEvents) + } + } + } + return nil +} diff --git a/cel/pkg/reconciler/celrun/controller.go b/cel/pkg/reconciler/celrun/controller.go new file mode 100644 index 000000000..90b028c07 --- /dev/null +++ b/cel/pkg/reconciler/celrun/controller.go @@ -0,0 +1,64 @@ +/* +Copyright 2021 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 celrun + +import ( + "context" + "github.com/tektoncd/experimental/cel/pkg/apis/cel" + celv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + celclient "github.com/tektoncd/experimental/cel/pkg/client/injection/client" + celinformer "github.com/tektoncd/experimental/cel/pkg/client/injection/informers/cel/v1alpha1/cel" + pipelineclient "github.com/tektoncd/pipeline/pkg/client/injection/client" + runinformer "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1alpha1/run" + runreconciler "github.com/tektoncd/pipeline/pkg/client/injection/reconciler/pipeline/v1alpha1/run" + pipelinecontroller "github.com/tektoncd/pipeline/pkg/controller" + "k8s.io/client-go/tools/cache" + "knative.dev/pkg/configmap" + "knative.dev/pkg/controller" +) + +// NewController instantiates a new controller.Impl from knative.dev/pkg/controller +func NewController(namespace string) func(context.Context, configmap.Watcher) *controller.Impl { + return func(ctx context.Context, cmw configmap.Watcher) *controller.Impl { + + pipelineclientset := pipelineclient.Get(ctx) + celclientset := celclient.Get(ctx) + runInformer := runinformer.Get(ctx) + celInformer := celinformer.Get(ctx) + + r := &Reconciler{ + pipelineClientSet: pipelineclientset, + CELClientSet: celclientset, + runLister: runInformer.Lister(), + CELLister: celInformer.Lister(), + } + + impl := runreconciler.NewImpl(ctx, r, func(impl *controller.Impl) controller.Options { + return controller.Options{ + AgentName: cel.ControllerName, + } + }) + + // Add event handler for Runs + runInformer.Informer().AddEventHandler(cache.FilteringResourceEventHandler{ + FilterFunc: pipelinecontroller.FilterRunRef(celv1alpha1.SchemeGroupVersion.String(), cel.ControllerName), + Handler: controller.HandleAll(impl.Enqueue), + }) + + return impl + } +} diff --git a/cel/test/build_logs.go b/cel/test/build_logs.go new file mode 100644 index 000000000..c192fefbe --- /dev/null +++ b/cel/test/build_logs.go @@ -0,0 +1,73 @@ +/* +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 + + 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 test + +import ( + "context" + "fmt" + "io/ioutil" + "strings" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "knative.dev/pkg/test/logging" +) + +func collectPodLogs(ctx context.Context, c *clients, podName, namespace string, logf logging.FormatLogger) { + logs, err := getContainersLogsFromPod(ctx, c.KubeClient, podName, namespace) + if err != nil { + logf("Could not get logs for pod %s: %s", podName, err) + } + logf("build logs %s", logs) +} + +func getContainersLogsFromPod(ctx context.Context, c kubernetes.Interface, pod, namespace string) (string, error) { + p, err := c.CoreV1().Pods(namespace).Get(ctx, pod, metav1.GetOptions{}) + if err != nil { + return "", err + } + + sb := strings.Builder{} + for _, container := range p.Spec.Containers { + sb.WriteString(fmt.Sprintf("\n>>> Container %s:\n", container.Name)) + logs, err := getContainerLogsFromPod(ctx, c, pod, container.Name, namespace) + if err != nil { + return "", err + } + sb.WriteString(logs) + } + return sb.String(), nil +} + +func getContainerLogsFromPod(ctx context.Context, c kubernetes.Interface, pod, container, namespace string) (string, error) { + sb := strings.Builder{} + // Do not follow, which will block until the Pod terminates, and potentially deadlock the test. + // If done in the wrong order, this could actually block things and prevent the Pod from being + // deleted at all. + req := c.CoreV1().Pods(namespace).GetLogs(pod, &corev1.PodLogOptions{Follow: false, Container: container}) + rc, err := req.Stream(ctx) + if err != nil { + return "", err + } + bs, err := ioutil.ReadAll(rc) + if err != nil { + return "", err + } + sb.Write(bs) + return sb.String(), nil +} diff --git a/cel/test/celrun_test.go b/cel/test/celrun_test.go new file mode 100644 index 000000000..50f208615 --- /dev/null +++ b/cel/test/celrun_test.go @@ -0,0 +1,422 @@ +//go:build e2e +// +build e2e + +/* +Copyright 2021 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 test + +import ( + "context" + "github.com/google/go-cmp/cmp" + "github.com/tektoncd/experimental/cel/pkg/apis/cel" + celv1alpha1 "github.com/tektoncd/experimental/cel/pkg/apis/cel/v1alpha1" + "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned" + resourceversioned "github.com/tektoncd/experimental/cel/pkg/client/clientset/versioned/typed/cel/v1alpha1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + tektontest "github.com/tektoncd/pipeline/test" + "github.com/tektoncd/pipeline/test/diff" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" + knativetest "knative.dev/pkg/test" + "regexp" + "testing" + "time" +) + +var ( + runTimeout = 10 * time.Minute +) + +// Expected events can be required or optional +type ev struct { + message string + required bool +} + +func TestCELRun(t *testing.T) { + t.Parallel() + + testcases := []struct { + name string + cel *celv1alpha1.CEL + run *v1alpha1.Run + expectedStatus corev1.ConditionStatus + expectedReason string + expectedResults []v1alpha1.RunResult + expectedMessage string + expectedEvents []ev + }{{ + name: "one expression successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "type(100)"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "int", + }}, + expectedEvents: []ev{ + {"", true}, + {"CEL expressions were evaluated successfully", true}, + }, + }, { + name: "multiple expressions successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "type(100)"}, + }, { + Name: "expr2", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "3 == 3"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "int", + }, { + Name: "expr2", + Value: "true", + }}, + expectedEvents: []ev{ + {"", true}, + {"CEL expressions were evaluated successfully", true}, + }, + }, { + name: "one expression and one variable successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Variables: []*v1beta1.Param{{ + Name: "var1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "foo"}, + }}, + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "var1 in ['foo', 'bar']"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "true", + }}, + expectedEvents: []ev{ + {"", true}, + {"CEL expressions were evaluated successfully", true}, + }, + }, { + name: "multiple expressions and multiple variable successful", + cel: &celv1alpha1.CEL{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel", + Namespace: "foo", + Labels: map[string]string{"myCelLabel": "myCelLabelValue"}, + Annotations: map[string]string{"myCelAnnotation": "myCelAnnotationValue"}, + }, + Spec: celv1alpha1.CELSpec{ + Variables: []*v1beta1.Param{{ + Name: "var1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "foo"}, + }, { + Name: "var2", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "bar"}, + }}, + Expressions: []*v1beta1.Param{{ + Name: "expr1", + Value: v1beta1.ArrayOrString{Type: v1beta1.ParamTypeString, StringVal: "'foo' in [var1, var2]"}, + }}, + }, + }, + run: &v1alpha1.Run{ + ObjectMeta: metav1.ObjectMeta{ + Name: "a-cel-run", + Namespace: "foo", + Labels: map[string]string{"myTestLabel": "myTestLabelValue"}, + Annotations: map[string]string{"myTestAnnotation": "myTestAnnotationValue"}, + }, + Spec: v1alpha1.RunSpec{ + Ref: &v1alpha1.TaskRef{ + APIVersion: celv1alpha1.SchemeGroupVersion.String(), + Kind: cel.ControllerName, + Name: "a-cel", + }, + }, + }, + expectedStatus: corev1.ConditionTrue, + expectedReason: celv1alpha1.CELRunReasonEvaluationSuccess.String(), + expectedMessage: "CEL expressions were evaluated successfully", + expectedResults: []v1alpha1.RunResult{{ + Name: "expr1", + Value: "true", + }}, + expectedEvents: []ev{ + {"", true}, + {"CEL expressions were evaluated successfully", true}, + }, + }} + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + tc := tc // Copy current tc to local variable due to test parallelization + t.Parallel() + ctx := context.Background() + ctx, cancel := context.WithCancel(ctx) + defer cancel() + c, namespace := setup(ctx, t) + CELClient := getCELClient(t, namespace) + + knativetest.CleanupOnInterrupt(func() { tearDown(ctx, t, c, namespace) }, t.Logf) + defer tearDown(ctx, t, c, namespace) + + if tc.cel != nil { + cel := tc.cel.DeepCopy() + cel.Namespace = namespace + if _, err := CELClient.Create(ctx, cel, metav1.CreateOptions{}); err != nil { + t.Fatalf("Failed to create CEL `%s`: %s", tc.cel.Name, err) + } + } + + run := tc.run.DeepCopy() + run.Namespace = namespace + run, err := c.RunClient.Create(ctx, run, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Failed to create Run `%s`: %s", run.Name, err) + } + + t.Logf("Waiting for Run %s in namespace %s to complete", run.Name, run.Namespace) + var inState tektontest.ConditionAccessorFn + var desc string + if tc.expectedStatus == corev1.ConditionTrue { + inState = tektontest.Succeed(run.Name) + desc = "RunSuccess" + } else { + inState = tektontest.FailedWithReason(tc.expectedReason, run.Name) + desc = "RunFailed" + } + if err := WaitForRunState(ctx, c, run.Name, runTimeout, inState, desc); err != nil { + t.Fatalf("Error waiting for Run %s/%s to finish: %s", run.Namespace, run.Name, err) + } + + t.Logf("Run %s in namespace %s completed - fetching it", run.Name, run.Namespace) + run, err = c.RunClient.Get(ctx, run.Name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("Couldn't get expected Run %s/%s: %s", run.Namespace, run.Name, err) + } + + t.Logf("Checking CEL status in the Run status") + status := &celv1alpha1.CELStatus{} + if err := run.Status.DecodeExtraFields(status); err != nil { + t.Errorf("DecodeExtraFields error: %v", err.Error()) + } + + t.Logf("Checking the status, reason and message in the Run's ConditionSucceeded") + checkRunCondition(t, run, tc.expectedStatus, tc.expectedReason, tc.expectedMessage) + + t.Logf("Verifying the expected results are produced") + if d := cmp.Diff(tc.expectedResults, run.Status.Results); d != "" { + t.Errorf("Status Results: %s", diff.PrintWantGot(d)) + } + + t.Logf("Checking events that were created from Run") + checkEvents(ctx, t, c, run, namespace, tc.expectedEvents) + }) + } +} + +func getCELClient(t *testing.T, namespace string) resourceversioned.CELInterface { + configPath := knativetest.Flags.Kubeconfig + clusterName := knativetest.Flags.Cluster + cfg, err := knativetest.BuildClientConfig(configPath, clusterName) + if err != nil { + t.Fatalf("failed to create configuration obj from %s for cluster %s: %s", configPath, clusterName, err) + } + cs, err := versioned.NewForConfig(cfg) + if err != nil { + t.Fatalf("failed to create cel clientset from config file at %s: %s", configPath, err) + } + return cs.CustomV1alpha1().CELs(namespace) +} + +func checkRunCondition(t *testing.T, run *v1alpha1.Run, expectedStatus corev1.ConditionStatus, expectedReason string, expectedMessage string) { + condition := run.Status.GetCondition(apis.ConditionSucceeded) + if condition == nil { + t.Error("Condition missing in Run") + } else { + if condition.Status != expectedStatus { + t.Errorf("Expected Run status to be %v but was %v", expectedStatus, condition) + } + if condition.Reason != expectedReason { + t.Errorf("Expected reason to be %q but was %q", expectedReason, condition.Reason) + } + if condition.Message != expectedMessage { + t.Errorf("Expected message to be %q but was %q", expectedMessage, condition.Message) + } + } + if run.Status.StartTime == nil { + t.Errorf("Expected Run start time to be set but it wasn't") + } + if expectedStatus == corev1.ConditionUnknown { + if run.Status.CompletionTime != nil { + t.Errorf("Expected Run completion time to not be set but it was") + } + } else if run.Status.CompletionTime == nil { + t.Errorf("Expected Run completion time to be set but it wasn't") + } +} + +func checkEvents(ctx context.Context, t *testing.T, c *clients, run *v1alpha1.Run, namespace string, expectedEvents []ev) { + matchKinds := map[string][]string{"Run": {run.Name}} + events, err := collectMatchingEvents(ctx, c.KubeClient, namespace, matchKinds) + if err != nil { + t.Fatalf("Failed to collect matching events: %q", err) + } + // Log the received events. + receivedEvents := make([]string, 0, len(events)) + for _, receivedEvent := range events { + receivedEvents = append(receivedEvents, receivedEvent.Message) + } + t.Logf("Received events: %q", receivedEvents) + // In the concurrency scenarios some events may or may not happen based on timing. + e := 0 + for _, expectedEvent := range expectedEvents { + if e >= len(events) { + if !expectedEvent.required { + continue + } + t.Errorf("Did not get expected event %q", expectedEvent.message) + continue + } + if matched, _ := regexp.MatchString(expectedEvent.message, events[e].Message); !matched { + if !expectedEvent.required { + continue + } + t.Errorf("Expected event %q but got %q", expectedEvent.message, events[e].Message) + } + e++ + } +} + +// collectMatchingEvents collects a list of events under 5 seconds that match certain objects by kind and name. +// This is copied from pipelinerun_test and modified to drop the reason parameter. +func collectMatchingEvents(ctx context.Context, kubeClient *knativetest.KubeClient, namespace string, kinds map[string][]string) ([]*corev1.Event, error) { + var events []*corev1.Event + + watchEvents, err := kubeClient.CoreV1().Events(namespace).Watch(ctx, metav1.ListOptions{}) + // close watchEvents channel + defer watchEvents.Stop() + if err != nil { + return events, err + } + + // create timer to not wait for events longer than 5 seconds + timer := time.NewTimer(5 * time.Second) + + for { + select { + case wevent := <-watchEvents.ResultChan(): + event := wevent.Object.(*corev1.Event) + if val, ok := kinds[event.InvolvedObject.Kind]; ok { + for _, expectedName := range val { + if event.InvolvedObject.Name == expectedName { + events = append(events, event) + } + } + } + case <-timer.C: + return events, nil + } + } +} diff --git a/cel/test/clients.go b/cel/test/clients.go new file mode 100644 index 000000000..a08a66879 --- /dev/null +++ b/cel/test/clients.go @@ -0,0 +1,79 @@ +/* +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 + + 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 test + +import ( + "testing" + + "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" + "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/typed/pipeline/v1alpha1" + "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/typed/pipeline/v1beta1" + resourceversioned "github.com/tektoncd/pipeline/pkg/client/resource/clientset/versioned" + resourcev1alpha1 "github.com/tektoncd/pipeline/pkg/client/resource/clientset/versioned/typed/resource/v1alpha1" + knativetest "knative.dev/pkg/test" +) + +// clients holds instances of interfaces for making requests to the Pipeline controllers. +type clients struct { + KubeClient *knativetest.KubeClient + + PipelineClient v1beta1.PipelineInterface + ClusterTaskClient v1beta1.ClusterTaskInterface + TaskClient v1beta1.TaskInterface + TaskRunClient v1beta1.TaskRunInterface + PipelineRunClient v1beta1.PipelineRunInterface + PipelineResourceClient resourcev1alpha1.PipelineResourceInterface + ConditionClient v1alpha1.ConditionInterface + RunClient v1alpha1.RunInterface +} + +// newClients instantiates and returns several clientsets required for making requests to the +// Pipeline cluster specified by the combination of clusterName and configPath. Clients can +// make requests within namespace. +func newClients(t *testing.T, configPath, clusterName, namespace string) *clients { + t.Helper() + var err error + c := &clients{} + + c.KubeClient, err = knativetest.NewKubeClient(configPath, clusterName) + if err != nil { + t.Fatalf("failed to create kubeclient from config file at %s: %s", configPath, err) + } + + cfg, err := knativetest.BuildClientConfig(configPath, clusterName) + if err != nil { + t.Fatalf("failed to create configuration obj from %s for cluster %s: %s", configPath, clusterName, err) + } + + cs, err := versioned.NewForConfig(cfg) + if err != nil { + t.Fatalf("failed to create pipeline clientset from config file at %s: %s", configPath, err) + } + rcs, err := resourceversioned.NewForConfig(cfg) + if err != nil { + t.Fatalf("failed to create pipeline clientset from config file at %s: %s", configPath, err) + } + c.PipelineClient = cs.TektonV1beta1().Pipelines(namespace) + c.ClusterTaskClient = cs.TektonV1beta1().ClusterTasks() + c.TaskClient = cs.TektonV1beta1().Tasks(namespace) + c.TaskRunClient = cs.TektonV1beta1().TaskRuns(namespace) + c.PipelineRunClient = cs.TektonV1beta1().PipelineRuns(namespace) + c.PipelineResourceClient = rcs.TektonV1alpha1().PipelineResources(namespace) + c.ConditionClient = cs.TektonV1alpha1().Conditions(namespace) + c.RunClient = cs.TektonV1alpha1().Runs(namespace) + return c +} diff --git a/cel/test/controller.go b/cel/test/controller.go index 77c6cefe0..7d9fd8734 100644 --- a/cel/test/controller.go +++ b/cel/test/controller.go @@ -19,6 +19,15 @@ package test import ( "context" "fmt" + "sync/atomic" + "testing" + + // Link in the fakes so they get injected into injection.Fake + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + fakepipelineclientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/fake" + informersv1alpha1 "github.com/tektoncd/pipeline/pkg/client/informers/externalversions/pipeline/v1alpha1" + informersv1beta1 "github.com/tektoncd/pipeline/pkg/client/informers/externalversions/pipeline/v1beta1" fakepipelineclient "github.com/tektoncd/pipeline/pkg/client/injection/client/fake" fakeconditioninformer "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1alpha1/condition/fake" fakeruninformer "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1alpha1/run/fake" @@ -27,35 +36,26 @@ import ( fakepipelineruninformer "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1beta1/pipelinerun/fake" faketaskinformer "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1beta1/task/fake" faketaskruninformer "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1beta1/taskrun/fake" + fakeresourceclientset "github.com/tektoncd/pipeline/pkg/client/resource/clientset/versioned/fake" + resourceinformersv1alpha1 "github.com/tektoncd/pipeline/pkg/client/resource/informers/externalversions/resource/v1alpha1" fakeresourceclient "github.com/tektoncd/pipeline/pkg/client/resource/injection/client/fake" fakeresourceinformer "github.com/tektoncd/pipeline/pkg/client/resource/injection/informers/resource/v1alpha1/pipelineresource/fake" + cloudeventclient "github.com/tektoncd/pipeline/pkg/reconciler/events/cloudevent" + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + coreinformers "k8s.io/client-go/informers/core/v1" + fakekubeclientset "k8s.io/client-go/kubernetes/fake" ktesting "k8s.io/client-go/testing" "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake" fakeconfigmapinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/configmap/fake" fakepodinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/pod/fake" fakeserviceaccountinformer "knative.dev/pkg/client/injection/kube/informers/core/v1/serviceaccount/fake" - "sync/atomic" - "testing" - - // Link in the fakes so they get injected into injection.Fake - "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" - "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" - fakepipelineclientset "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/fake" - informersv1alpha1 "github.com/tektoncd/pipeline/pkg/client/informers/externalversions/pipeline/v1alpha1" - informersv1beta1 "github.com/tektoncd/pipeline/pkg/client/informers/externalversions/pipeline/v1beta1" - fakeresourceclientset "github.com/tektoncd/pipeline/pkg/client/resource/clientset/versioned/fake" - resourceinformersv1alpha1 "github.com/tektoncd/pipeline/pkg/client/resource/informers/externalversions/resource/v1alpha1" - cloudeventclient "github.com/tektoncd/pipeline/pkg/reconciler/events/cloudevent" - "go.uber.org/zap" - corev1 "k8s.io/api/core/v1" - coreinformers "k8s.io/client-go/informers/core/v1" - fakekubeclientset "k8s.io/client-go/kubernetes/fake" - "k8s.io/client-go/tools/record" "knative.dev/pkg/controller" ) diff --git a/cel/test/e2e-cels.sh b/cel/test/e2e-cels.sh new file mode 100755 index 000000000..38725d6b3 --- /dev/null +++ b/cel/test/e2e-cels.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash + +# Copyright 2021 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. + +# Helper functions for E2E tests. + +source $(git rev-parse --show-toplevel)/vendor/github.com/tektoncd/plumbing/scripts/e2e-tests.sh + +function install_cel_crd() { + echo ">> Deploying CEL custom task" + ko resolve -f config/ \ + | sed -e 's%"level": "info"%"level": "debug"%' \ + | sed -e 's%loglevel.controller: "info"%loglevel.controller: "debug"%' \ + | sed -e 's%loglevel.webhook: "info"%loglevel.webhook: "debug"%' \ + | kubectl apply -f - || fail_test "Build pipeline installation failed" + verify_cel_installation +} + +function verify_cel_installation() { + # Make sure that everything is cleaned up in the current namespace + delete_cel_resources + + # Wait for pods to be running in the namespaces we are deploying to + wait_until_pods_running tekton-pipelines || fail_test "CEL controller or webhook did not come up" +} + +function uninstall_cel_crd() { + echo ">> Uninstalling CEL custom task" + ko delete --ignore-not-found=true -f ${REPO_ROOT_DIR}/cel/config/ + + # Make sure that everything is cleaned up in the current namespace. + delete_cel_resources +} + +function delete_cel_resources() { + for res in run; do + kubectl delete --ignore-not-found=true ${res}.tekton.dev -l kind=CEL + done + for res in cel; do + kubectl delete --ignore-not-found=true ${res}.custom.tekton.dev --all + done +} diff --git a/cel/test/e2e-common.sh b/cel/test/e2e-common.sh new file mode 100755 index 000000000..1fba02495 --- /dev/null +++ b/cel/test/e2e-common.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +# 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 +# +# 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. + +# Helper functions for E2E tests. + +source $(git rev-parse --show-toplevel)/vendor/github.com/tektoncd/plumbing/scripts/e2e-tests.sh + +function install_pipeline_crd() { + echo ">> Deploying Tekton Pipelines" + ko resolve -f config/ \ + | sed -e 's%"level": "info"%"level": "debug"%' \ + | sed -e 's%loglevel.controller: "info"%loglevel.controller: "debug"%' \ + | sed -e 's%loglevel.webhook: "info"%loglevel.webhook: "debug"%' \ + | kubectl apply -f - || fail_test "Build pipeline installation failed" + verify_pipeline_installation +} + +# Install the Tekton pipeline crd based on the release number +function install_pipeline_crd_version() { + echo ">> Deploying Tekton Pipelines of Version $1" + kubectl apply -f "https://github.com/tektoncd/pipeline/releases/download/$1/release.yaml" || fail_test "Build pipeline installation failed of Version $1" + verify_pipeline_installation +} + +function verify_pipeline_installation() { + # Make sure that everything is cleaned up in the current namespace. + delete_pipeline_resources + + # Wait for pods to be running in the namespaces we are deploying to + wait_until_pods_running tekton-pipelines || fail_test "Tekton Pipeline did not come up" +} + +function uninstall_pipeline_crd() { + echo ">> Uninstalling Tekton Pipelines" + ko delete --ignore-not-found=true -f config/ + + # Make sure that everything is cleaned up in the current namespace. + delete_pipeline_resources +} + +function uninstall_pipeline_crd_version() { + echo ">> Uninstalling Tekton Pipelines of version $1" + kubectl delete --ignore-not-found=true -f "https://github.com/tektoncd/pipeline/releases/download/$1/release.yaml" + + # Make sure that everything is cleaned up in the current namespace. + delete_pipeline_resources +} + +function delete_pipeline_resources() { + for res in conditions pipelineresources tasks clustertasks pipelines taskruns pipelineruns; do + kubectl delete --ignore-not-found=true ${res}.tekton.dev --all + done +} diff --git a/cel/test/e2e-tests.sh b/cel/test/e2e-tests.sh new file mode 100755 index 000000000..f2e180186 --- /dev/null +++ b/cel/test/e2e-tests.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Copyright 2021 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. + +# This script calls out to scripts in tektoncd/plumbing to setup a cluster +# and deploy Tekton Pipelines to it for running integration tests. + +source $(git rev-parse --show-toplevel)/cel/test/e2e-common.sh +source $(git rev-parse --show-toplevel)/cel/test/e2e-cels.sh + +# Script entry point. + +initialize $@ + +# initialize function does a CD to REPO_ROOT_DIR so we have to CD back here. +cd ${REPO_ROOT_DIR}/cel + +header "Setting up environment" + +install_pipeline_crd_version v0.20.1 + +install_cel_crd + +failed=0 + +# Run the integration tests +header "Running Go e2e tests" +go_test_e2e -timeout=20m ./test/... || failed=1 + +(( failed )) && fail_test +success diff --git a/cel/test/init_test.go b/cel/test/init_test.go new file mode 100644 index 000000000..9c74da1c3 --- /dev/null +++ b/cel/test/init_test.go @@ -0,0 +1,234 @@ +//go:build e2e || examples +// +build e2e examples + +/* +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 + + 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. +*/ + +// This file contains initialization logic for the tests, such as special magical global state that needs to be initialized. + +package test + +import ( + "context" + "flag" + "fmt" + "github.com/ghodss/yaml" + "github.com/tektoncd/pipeline/pkg/names" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // Mysteriously by k8s libs, or they fail to create `KubeClient`s when using oidc authentication. Apparently just importing it is enough. @_@ side effects @_@. https://github.com/kubernetes/client-go/issues/345 + _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" + knativetest "knative.dev/pkg/test" + "knative.dev/pkg/test/logging" // Mysteriously by k8s libs, or they fail to create `KubeClient`s from config. Apparently just importing it is enough. @_@ side effects @_@. https://github.com/kubernetes/client-go/issues/242 + "os" + "strings" + "sync" + "testing" +) + +var initMetrics sync.Once + +func setup(ctx context.Context, t *testing.T, fn ...func(context.Context, *testing.T, *clients, string)) (*clients, string) { + t.Helper() + namespace := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("arendelle") + + initializeLogsAndMetrics(t) + + c := newClients(t, knativetest.Flags.Kubeconfig, knativetest.Flags.Cluster, namespace) + createNamespace(ctx, t, namespace, c.KubeClient) + verifyServiceAccountExistence(ctx, t, namespace, c.KubeClient) + + for _, f := range fn { + f(ctx, t, c, namespace) + } + + return c, namespace +} + +func header(t *testing.T, text string) { + t.Helper() + left := "### " + right := " ###" + txt := left + text + right + bar := strings.Repeat("#", len(txt)) + t.Logf(bar) + t.Logf(txt) + t.Logf(bar) +} + +func tearDown(ctx context.Context, t *testing.T, cs *clients, namespace string) { + t.Helper() + if cs.KubeClient == nil { + return + } + if t.Failed() { + header(t, fmt.Sprintf("Dumping objects from %s", namespace)) + bs, err := getCRDYaml(ctx, cs, namespace) + if err != nil { + t.Error(err) + } else { + t.Log(string(bs)) + } + header(t, fmt.Sprintf("Dumping logs from Pods in the %s", namespace)) + taskruns, err := cs.TaskRunClient.List(ctx, metav1.ListOptions{}) + if err != nil { + t.Errorf("Error getting Runs list %s", err) + } + for _, tr := range taskruns.Items { + if tr.Status.PodName != "" { + collectPodLogs(ctx, cs, tr.Status.PodName, namespace, t.Logf) + } + } + } + + if os.Getenv("TEST_KEEP_NAMESPACES") == "" && !t.Failed() { + t.Logf("Deleting namespace %s", namespace) + if err := cs.KubeClient.CoreV1().Namespaces().Delete(ctx, namespace, metav1.DeleteOptions{}); err != nil { + t.Errorf("Failed to delete namespace %s: %s", namespace, err) + } + } +} + +func initializeLogsAndMetrics(t *testing.T) { + initMetrics.Do(func() { + flag.Parse() + flag.Set("alsologtostderr", "true") + logging.InitializeLogger() + + //if knativetest.Flags.EmitMetrics { + logging.InitializeMetricExporter(t.Name()) + //} + }) +} + +func createNamespace(ctx context.Context, t *testing.T, namespace string, kubeClient *knativetest.KubeClient) { + t.Logf("Create namespace %s to deploy to", namespace) + labels := map[string]string{ + "tekton.dev/test-e2e": "true", + } + if _, err := kubeClient.CoreV1().Namespaces().Create(ctx, &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + Labels: labels, + }, + }, metav1.CreateOptions{}); err != nil { + t.Fatalf("Failed to create namespace %s for tests: %s", namespace, err) + } +} + +func verifyServiceAccountExistence(ctx context.Context, t *testing.T, namespace string, kubeClient *knativetest.KubeClient) { + defaultSA := "default" + t.Logf("Verify SA %q is created in namespace %q", defaultSA, namespace) + + if err := wait.PollImmediate(interval, timeout, func() (bool, error) { + _, err := kubeClient.CoreV1().ServiceAccounts(namespace).Get(ctx, defaultSA, metav1.GetOptions{}) + if err != nil && errors.IsNotFound(err) { + return false, nil + } + return true, err + }); err != nil { + t.Fatalf("Failed to get SA %q in namespace %q for tests: %s", defaultSA, namespace, err) + } +} + +// TestMain initializes anything global needed by the tests. Right now this is just log and metric +// setup since the log and metric libs we're using use global state :( +func TestMain(m *testing.M) { + flag.Parse() + c := m.Run() + fmt.Fprintf(os.Stderr, "Using kubeconfig at `%s` with cluster `%s`\n", knativetest.Flags.Kubeconfig, knativetest.Flags.Cluster) + os.Exit(c) +} + +func getCRDYaml(ctx context.Context, cs *clients, ns string) ([]byte, error) { + var output []byte + printOrAdd := func(i interface{}) { + bs, err := yaml.Marshal(i) + if err != nil { + return + } + output = append(output, []byte("\n---\n")...) + output = append(output, bs...) + } + + ps, err := cs.PipelineClient.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get pipeline: %w", err) + } + for _, i := range ps.Items { + printOrAdd(i) + } + + prs, err := cs.PipelineResourceClient.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get pipelinerun resource: %w", err) + } + for _, i := range prs.Items { + printOrAdd(i) + } + + prrs, err := cs.PipelineRunClient.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get pipelinerun: %w", err) + } + for _, i := range prrs.Items { + printOrAdd(i) + } + + ts, err := cs.TaskClient.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get tasks: %w", err) + } + for _, i := range ts.Items { + printOrAdd(i) + } + + cts, err := cs.ClusterTaskClient.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get clustertasks: %w", err) + } + for _, i := range cts.Items { + printOrAdd(i) + } + + trs, err := cs.TaskRunClient.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get taskruns: %w", err) + } + for _, i := range trs.Items { + printOrAdd(i) + } + + rs, err := cs.RunClient.List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get runs: %v", err) + } + for _, i := range rs.Items { + printOrAdd(i) + } + + pods, err := cs.KubeClient.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{}) + if err != nil { + return nil, fmt.Errorf("could not get pods: %w", err) + } + for _, i := range pods.Items { + printOrAdd(i) + } + + return output, nil +} diff --git a/cel/test/wait.go b/cel/test/wait.go new file mode 100644 index 000000000..48714ff06 --- /dev/null +++ b/cel/test/wait.go @@ -0,0 +1,64 @@ +/* +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 + + 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 test + +import ( + "context" + "fmt" + tektontest "github.com/tektoncd/pipeline/test" + "time" + + "go.opencensus.io/trace" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" +) + +const ( + interval = 1 * time.Second + timeout = 10 * time.Minute +) + +func pollImmediateWithContext(ctx context.Context, fn func() (bool, error)) error { + return wait.PollImmediate(interval, timeout, func() (bool, error) { + select { + case <-ctx.Done(): + return true, ctx.Err() + default: + } + return fn() + }) +} + +// WaitForRunState polls the status of the Run called name from client every +// interval until inState returns `true` indicating it is done, returns an +// error or timeout. desc will be used to name the metric that is emitted to +// track how long it took for name to get into the state checked by inState. +func WaitForRunState(ctx context.Context, c *clients, name string, polltimeout time.Duration, inState tektontest.ConditionAccessorFn, desc string) error { + metricName := fmt.Sprintf("WaitForRunState/%s/%s", name, desc) + _, span := trace.StartSpan(context.Background(), metricName) + defer span.End() + + ctx, cancel := context.WithTimeout(ctx, polltimeout) + defer cancel() + return pollImmediateWithContext(ctx, func() (bool, error) { + r, err := c.RunClient.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return true, err + } + return inState(&r.Status) + }) +}