From 798d4668a3581d2d3c2cd4810f5c0afe38d813e3 Mon Sep 17 00:00:00 2001 From: zhhray Date: Mon, 9 May 2022 16:06:00 +0800 Subject: [PATCH] Helmrequest version is upgraded to V1 to support OCI Chart installation (#110) * Helmrequest version is upgraded to V1 to support OCI Chart installation Co-authored-by: huizhang --- .gitignore | 2 + Dockerfile | 2 +- Dockerfile.arm | 2 +- Dockerfile.github | 2 +- artifacts/all/deploy.yaml | 509 ++++++++++++++++-- artifacts/all/release.yaml | 509 ++++++++++++++++-- artifacts/crd/chartrepo/stable.yaml | 4 - charts/captain/Chart.yaml | 2 +- charts/captain/templates/chart.yaml | 110 +++- charts/captain/templates/chartrepo.yaml | 175 +++++- charts/captain/templates/crd.yaml | 226 +++++++- charts/captain/values.yaml | 2 +- config/crd/bases/chart.yaml | 110 +++- config/crd/bases/chartrepo.yaml | 175 +++++- config/crd/bases/crd.yaml | 226 +++++++- controllers/chartrepo_controller.go | 37 +- docs/en/crd.md | 37 ++ docs/en/crds/helmrequest.md | 37 +- docs/zh/ano.md | 18 +- docs/zh/crds/helmrequest.md | 39 +- go.mod | 13 +- go.sum | 220 +++++++- main.go | 27 +- pkg/chartrepo/default.go | 2 +- .../apis/clusterregistry/v1alpha1/types.go | 2 +- pkg/config/options.go | 1 + pkg/controller/clusterwatch.go | 22 +- pkg/controller/controller.go | 92 ++-- pkg/controller/dependency.go | 10 +- pkg/controller/event.go | 6 +- pkg/controller/eventhandler.go | 71 ++- pkg/controller/helmrequest.go | 79 +-- pkg/controller/sync.go | 13 +- pkg/controller/sync_test.go | 8 +- pkg/helm/common.go | 36 +- pkg/helm/download.go | 157 ++++-- pkg/helm/status.go | 55 +- pkg/helm/sync.go | 35 +- pkg/helm/values.go | 6 +- pkg/helmrequest/types.go | 4 +- pkg/helmrequest/yaml.go | 224 +++++++- pkg/registry/client.go | 108 ++-- pkg/registry/client_opts.go | 7 + pkg/registry/client_test.go | 6 +- pkg/webhook/handler.go | 5 +- 45 files changed, 2880 insertions(+), 553 deletions(-) diff --git a/.gitignore b/.gitignore index 83c353c7..f12fcb5a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ artifacts/coverage.out cover.out bin/manager bin/ +Dockerfile.local +local-build.sh diff --git a/Dockerfile b/Dockerfile index 72069bab..9a1553dc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ RUN go build -ldflags '-w -s' -a -installsuffix cgo -o manager main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details # FROM gcr.azk8s.cn/distroless/static:latest -FROM alpine:3.14 +FROM alpine:3.15 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && apk update && apk add subversion RUN echo 'hosts: files dns' > /etc/nsswitch.conf diff --git a/Dockerfile.arm b/Dockerfile.arm index b52d8c45..3cf0d826 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -1,4 +1,4 @@ -FROM arm64v8/alpine:3.11 +FROM arm64v8/alpine:3.15 RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && apk update && apk add subversion RUN echo 'hosts: files dns' > /etc/nsswitch.conf diff --git a/Dockerfile.github b/Dockerfile.github index 5433854a..0454a662 100644 --- a/Dockerfile.github +++ b/Dockerfile.github @@ -23,7 +23,7 @@ RUN CGO_ENABLED=0 GOOS=linux GO111MODULE=on go build -a -o manager main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details # FROM gcr.azk8s.cn/distroless/static:latest -FROM alpine:3.14 +FROM alpine:3.15 RUN apk update && apk add subversion RUN echo 'hosts: files dns' > /etc/nsswitch.conf diff --git a/artifacts/all/deploy.yaml b/artifacts/all/deploy.yaml index cc012533..b95cadea 100644 --- a/artifacts/all/deploy.yaml +++ b/artifacts/all/deploy.yaml @@ -17,7 +17,7 @@ spec: - hrs scope: Namespaced versions: - - name: v1alpha1 + - name: v1 additionalPrinterColumns: - name: Chart type: string @@ -89,6 +89,37 @@ spec: multi clusters, we may have different HelmRequest name(with cluster prefix or suffix) and same release name type: string + source: + description: Source defines the source of chart, If this field is + set, Chart and Version field will be ignored(useless) + properties: + http: + properties: + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + url: + description: URL is the URL of the http(s) endpoint + type: string + required: + - url + type: object + oci: + properties: + repo: + description: Repo is the repo of the oci artifact + type: string + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + required: + - repo + type: object + type: object values: description: Values represents a collection of chart values. type: object @@ -208,83 +239,459 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + additionalPrinterColumns: + - name: Chart + type: string + description: The chart of this HelmRequest + jsonPath: .spec.chart + - name: Version + type: string + description: Version of this chart + jsonPath: .spec.version + - name: Namespace + type: string + description: The namespace which the chart deployed to + jsonPath: .spec.namespace + - name: AllCluster + type: boolean + description: Is this chart will be installed to all cluster + jsonPath: .spec.installToAllClusters + - name: Phase + type: string + description: The phase of this HelmRequest + jsonPath: .status.phase + - name: Age + type: date + jsonPath: .metadata.creationTimestamp + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + chart: + type: string + clusterName: + description: ClusterName is the cluster where the chart will be installed. + If InstallToAllClusters=true, this field will be ignored + type: string + dependencies: + description: Dependencies is the dependencies of this HelmRequest, + it's a list of there names THe dependencies must lives in the same + namespace, and each of them must be in Synced status before we sync + this HelmRequest + items: + type: string + type: array + installToAllClusters: + description: InstallToAllClusters will install this chart to all available + clusters, even the cluster was created after this chart. If this + field is true, ClusterName will be ignored(useless) + type: boolean + namespace: + description: Namespace is the namespace where the Release object will + be lived in. Notes this should be used with the values defined in + the chart, otherwise the install will failed + type: string + releaseName: + description: ReleaseName is the Release name to be generated, default + to HelmRequest.Name. If we want to manually install this chart to + multi clusters, we may have different HelmRequest name(with cluster + prefix or suffix) and same release name + type: string + values: + description: Values represents a collection of chart values. + type: object + nullable: true + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + description: ValuesFrom represents values from ConfigMap/Secret... + items: + description: ValuesFromSource represents a source of values, only + one of it's fields may be set + properties: + configMapKeyRef: + description: ConfigMapKeyRef selects a key of a ConfigMap + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key must + be defined + type: boolean + required: + - key + type: object + secretKeyRef: + description: SecretKeyRef selects a key of a Secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + type: array + version: + type: string + type: object + status: + properties: + conditions: + items: + properties: + lastProbeTime: + description: Last time we probed the condition. + format: date-time + type: string + nullable: true + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + nullable: true + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + description: 'Status is the status of the condition. Can be + True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: + description: 'Type is the type of the condition. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: object + type: array + lastSpecHash: + description: LastSpecHash store the has value of the synced spec, + if this value not equal to the current one, means we need to do + a update for the chart + type: string + notes: + description: Notes is the contents from helm (after helm install successfully + it will be printed to the console + type: string + phase: + description: HelmRequestPhase is a label for the condition of a HelmRequest + at the current time. + type: string + reason: + description: Reason will store the reason why the HelmRequest deploy + failed + type: string + syncedClusters: + description: SyncedClusters will store the synced clusters if InstallToAllClusters + is true + items: + type: string + type: array + version: + description: Verions is the real version that installed + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: chartrepos.app.alauda.io spec: + conversion: + strategy: None group: app.alauda.io - versions: - - name: v1alpha1 - served: true - storage: false - schema: - openAPIV3Schema: - properties: - spec: - required: - - url - - name: v1beta1 - served: true - storage: true - schema: - openAPIV3Schema: - properties: - spec: - required: - - url - - type names: kind: ChartRepo listKind: ChartRepoList plural: chartrepos - singular: chartrepo shortNames: - - ctr - additionalPrinterColumns: - - name: URL + - ctr + singular: chartrepo + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL type: string - description: The url of this chart repo - JSONPath: .spec.url - - name: Phase + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase type: string - description: The phase of this ChartRepo - JSONPath: .status.phase - - name: Age + - jsonPath: .metadata.creationTimestamp + name: Age type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + url: + description: URL is the repo's url + type: string + required: + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL + type: string + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + source: + description: new in v1beta1.if type is Chart, this is optional and + it will provide some compatible with v1alpha1 + properties: + path: + description: may be root, may be a subdir + type: string + url: + description: vcs url + type: string + required: + - url + nullable: true + type: object + type: + description: new in v1beta1 + type: string + url: + description: URL is the repo's url + type: string + required: + - type + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: true --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: charts.app.alauda.io spec: + conversion: + strategy: None group: app.alauda.io - versions: - - name: v1alpha1 - served: true - storage: false - - name: v1beta1 - served: true - storage: true names: kind: Chart listKind: ChartList plural: charts singular: chart - additionalPrinterColumns: - - name: Version + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version type: string - JSONPath: .spec.versions[0].version - - name: AppVersion + - jsonPath: .spec.versions[0].appVersion + name: AppVersion type: string - JSONPath: .spec.versions[0].appVersion - - name: Age + - jsonPath: .metadata.creationTimestamp + name: Age type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version + type: string + - jsonPath: .spec.versions[0].appVersion + name: AppVersion + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: true --- apiVersion: v1 kind: Service @@ -335,7 +742,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - image: alaudapublic/captain:v1.4.0 + image: alaudapublic/captain:v1.5.0 imagePullPolicy: IfNotPresent name: manager resources: diff --git a/artifacts/all/release.yaml b/artifacts/all/release.yaml index 1a9fa6a4..ec49680a 100644 --- a/artifacts/all/release.yaml +++ b/artifacts/all/release.yaml @@ -17,7 +17,7 @@ spec: - hrs scope: Namespaced versions: - - name: v1alpha1 + - name: v1 additionalPrinterColumns: - name: Chart type: string @@ -89,6 +89,37 @@ spec: multi clusters, we may have different HelmRequest name(with cluster prefix or suffix) and same release name type: string + source: + description: Source defines the source of chart, If this field is + set, Chart and Version field will be ignored(useless) + properties: + http: + properties: + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + url: + description: URL is the URL of the http(s) endpoint + type: string + required: + - url + type: object + oci: + properties: + repo: + description: Repo is the repo of the oci artifact + type: string + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + required: + - repo + type: object + type: object values: description: Values represents a collection of chart values. type: object @@ -208,83 +239,459 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + additionalPrinterColumns: + - name: Chart + type: string + description: The chart of this HelmRequest + jsonPath: .spec.chart + - name: Version + type: string + description: Version of this chart + jsonPath: .spec.version + - name: Namespace + type: string + description: The namespace which the chart deployed to + jsonPath: .spec.namespace + - name: AllCluster + type: boolean + description: Is this chart will be installed to all cluster + jsonPath: .spec.installToAllClusters + - name: Phase + type: string + description: The phase of this HelmRequest + jsonPath: .status.phase + - name: Age + type: date + jsonPath: .metadata.creationTimestamp + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + chart: + type: string + clusterName: + description: ClusterName is the cluster where the chart will be installed. + If InstallToAllClusters=true, this field will be ignored + type: string + dependencies: + description: Dependencies is the dependencies of this HelmRequest, + it's a list of there names THe dependencies must lives in the same + namespace, and each of them must be in Synced status before we sync + this HelmRequest + items: + type: string + type: array + installToAllClusters: + description: InstallToAllClusters will install this chart to all available + clusters, even the cluster was created after this chart. If this + field is true, ClusterName will be ignored(useless) + type: boolean + namespace: + description: Namespace is the namespace where the Release object will + be lived in. Notes this should be used with the values defined in + the chart, otherwise the install will failed + type: string + releaseName: + description: ReleaseName is the Release name to be generated, default + to HelmRequest.Name. If we want to manually install this chart to + multi clusters, we may have different HelmRequest name(with cluster + prefix or suffix) and same release name + type: string + values: + description: Values represents a collection of chart values. + type: object + nullable: true + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + description: ValuesFrom represents values from ConfigMap/Secret... + items: + description: ValuesFromSource represents a source of values, only + one of it's fields may be set + properties: + configMapKeyRef: + description: ConfigMapKeyRef selects a key of a ConfigMap + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key must + be defined + type: boolean + required: + - key + type: object + secretKeyRef: + description: SecretKeyRef selects a key of a Secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + type: array + version: + type: string + type: object + status: + properties: + conditions: + items: + properties: + lastProbeTime: + description: Last time we probed the condition. + format: date-time + type: string + nullable: true + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + nullable: true + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + description: 'Status is the status of the condition. Can be + True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: + description: 'Type is the type of the condition. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: object + type: array + lastSpecHash: + description: LastSpecHash store the has value of the synced spec, + if this value not equal to the current one, means we need to do + a update for the chart + type: string + notes: + description: Notes is the contents from helm (after helm install successfully + it will be printed to the console + type: string + phase: + description: HelmRequestPhase is a label for the condition of a HelmRequest + at the current time. + type: string + reason: + description: Reason will store the reason why the HelmRequest deploy + failed + type: string + syncedClusters: + description: SyncedClusters will store the synced clusters if InstallToAllClusters + is true + items: + type: string + type: array + version: + description: Verions is the real version that installed + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: chartrepos.app.alauda.io spec: + conversion: + strategy: None group: app.alauda.io - versions: - - name: v1alpha1 - served: true - storage: false - schema: - openAPIV3Schema: - properties: - spec: - required: - - url - - name: v1beta1 - served: true - storage: true - schema: - openAPIV3Schema: - properties: - spec: - required: - - url - - type names: kind: ChartRepo listKind: ChartRepoList plural: chartrepos - singular: chartrepo shortNames: - - ctr - additionalPrinterColumns: - - name: URL + - ctr + singular: chartrepo + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL type: string - description: The url of this chart repo - JSONPath: .spec.url - - name: Phase + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase type: string - description: The phase of this ChartRepo - JSONPath: .status.phase - - name: Age + - jsonPath: .metadata.creationTimestamp + name: Age type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + url: + description: URL is the repo's url + type: string + required: + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL + type: string + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + source: + description: new in v1beta1.if type is Chart, this is optional and + it will provide some compatible with v1alpha1 + properties: + path: + description: may be root, may be a subdir + type: string + url: + description: vcs url + type: string + required: + - url + nullable: true + type: object + type: + description: new in v1beta1 + type: string + url: + description: URL is the repo's url + type: string + required: + - type + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: true --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: charts.app.alauda.io spec: + conversion: + strategy: None group: app.alauda.io - versions: - - name: v1alpha1 - served: true - storage: false - - name: v1beta1 - served: true - storage: true names: kind: Chart listKind: ChartList plural: charts singular: chart - additionalPrinterColumns: - - name: Version + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version type: string - JSONPath: .spec.versions[0].version - - name: AppVersion + - jsonPath: .spec.versions[0].appVersion + name: AppVersion type: string - JSONPath: .spec.versions[0].appVersion - - name: Age + - jsonPath: .metadata.creationTimestamp + name: Age type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version + type: string + - jsonPath: .spec.versions[0].appVersion + name: AppVersion + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: true --- apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration @@ -402,7 +809,7 @@ spec: fieldRef: apiVersion: v1 fieldPath: metadata.namespace - image: harbor.alauda.cn/acp/captain:v1.4.0 + image: harbor.alauda.cn/acp/captain:v1.5.0 imagePullPolicy: IfNotPresent name: manager resources: diff --git a/artifacts/crd/chartrepo/stable.yaml b/artifacts/crd/chartrepo/stable.yaml index 2bf7be25..56cd779f 100644 --- a/artifacts/crd/chartrepo/stable.yaml +++ b/artifacts/crd/chartrepo/stable.yaml @@ -1,9 +1,5 @@ apiVersion: app.alauda.io/v1alpha1 kind: ChartRepo -metadata: - name: alauda -spec: - url: https://alauda.github.io/chartskind: ChartRepo metadata: name: stable spec: diff --git a/charts/captain/Chart.yaml b/charts/captain/Chart.yaml index e3ba392d..847dccb7 100644 --- a/charts/captain/Chart.yaml +++ b/charts/captain/Chart.yaml @@ -1,4 +1,4 @@ name: captain appVersion: "2.0" -version: v0.9.3 +version: v1.5.0 description: A Helm3 Controller diff --git a/charts/captain/templates/chart.yaml b/charts/captain/templates/chart.yaml index 8c1b393c..461cf969 100644 --- a/charts/captain/templates/chart.yaml +++ b/charts/captain/templates/chart.yaml @@ -1,23 +1,93 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: charts.app.alauda.io + name: charts.app.alauda.io spec: - group: app.alauda.io - version: v1alpha1 - names: - kind: Chart - listKind: ChartList - plural: charts - singular: chart - additionalPrinterColumns: - - name: Version - type: string - JSONPath: .spec.versions[0].version - - name: AppVersion - type: string - JSONPath: .spec.versions[0].appVersion - - name: Age - type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced \ No newline at end of file + conversion: + strategy: None + group: app.alauda.io + names: + kind: Chart + listKind: ChartList + plural: charts + singular: chart + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version + type: string + - jsonPath: .spec.versions[0].appVersion + name: AppVersion + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version + type: string + - jsonPath: .spec.versions[0].appVersion + name: AppVersion + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/charts/captain/templates/chartrepo.yaml b/charts/captain/templates/chartrepo.yaml index a90dd65d..490dc13e 100644 --- a/charts/captain/templates/chartrepo.yaml +++ b/charts/captain/templates/chartrepo.yaml @@ -1,34 +1,167 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: chartrepos.app.alauda.io spec: + conversion: + strategy: None group: app.alauda.io - version: v1alpha1 names: kind: ChartRepo listKind: ChartRepoList plural: chartrepos - singular: chartrepo shortNames: - - ctr - additionalPrinterColumns: - - name: URL + - ctr + singular: chartrepo + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL type: string - description: The url of this chart repo - JSONPath: .spec.url - - name: Phase + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase type: string - description: The phase of this ChartRepo - JSONPath: .status.phase - - name: Age + - jsonPath: .metadata.creationTimestamp + name: Age type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced - validation: - # openAPIV3Schema is the schema for validating custom objects. - openAPIV3Schema: - properties: - spec: - required: - - url \ No newline at end of file + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + url: + description: URL is the repo's url + type: string + required: + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL + type: string + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + source: + description: new in v1beta1.if type is Chart, this is optional and + it will provide some compatible with v1alpha1 + properties: + path: + description: may be root, may be a subdir + type: string + url: + description: vcs url + type: string + required: + - url + nullable: true + type: object + type: + description: new in v1beta1 + type: string + url: + description: URL is the repo's url + type: string + required: + - type + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/charts/captain/templates/crd.yaml b/charts/captain/templates/crd.yaml index b8ff41c5..0c1beb5e 100644 --- a/charts/captain/templates/crd.yaml +++ b/charts/captain/templates/crd.yaml @@ -16,7 +16,7 @@ spec: - hrs scope: Namespaced versions: - - name: v1alpha1 + - name: v1 additionalPrinterColumns: - name: Chart type: string @@ -88,6 +88,37 @@ spec: multi clusters, we may have different HelmRequest name(with cluster prefix or suffix) and same release name type: string + source: + description: Source defines the source of chart, If this field is + set, Chart and Version field will be ignored(useless) + properties: + http: + properties: + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + url: + description: URL is the URL of the http(s) endpoint + type: string + required: + - url + type: object + oci: + properties: + repo: + description: Repo is the repo of the oci artifact + type: string + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + required: + - repo + type: object + type: object values: description: Values represents a collection of chart values. type: object @@ -206,4 +237,195 @@ spec: served: true storage: true subresources: - status: {} \ No newline at end of file + status: {} + - name: v1alpha1 + additionalPrinterColumns: + - name: Chart + type: string + description: The chart of this HelmRequest + jsonPath: .spec.chart + - name: Version + type: string + description: Version of this chart + jsonPath: .spec.version + - name: Namespace + type: string + description: The namespace which the chart deployed to + jsonPath: .spec.namespace + - name: AllCluster + type: boolean + description: Is this chart will be installed to all cluster + jsonPath: .spec.installToAllClusters + - name: Phase + type: string + description: The phase of this HelmRequest + jsonPath: .status.phase + - name: Age + type: date + jsonPath: .metadata.creationTimestamp + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + chart: + type: string + clusterName: + description: ClusterName is the cluster where the chart will be installed. + If InstallToAllClusters=true, this field will be ignored + type: string + dependencies: + description: Dependencies is the dependencies of this HelmRequest, + it's a list of there names THe dependencies must lives in the same + namespace, and each of them must be in Synced status before we sync + this HelmRequest + items: + type: string + type: array + installToAllClusters: + description: InstallToAllClusters will install this chart to all available + clusters, even the cluster was created after this chart. If this + field is true, ClusterName will be ignored(useless) + type: boolean + namespace: + description: Namespace is the namespace where the Release object will + be lived in. Notes this should be used with the values defined in + the chart, otherwise the install will failed + type: string + releaseName: + description: ReleaseName is the Release name to be generated, default + to HelmRequest.Name. If we want to manually install this chart to + multi clusters, we may have different HelmRequest name(with cluster + prefix or suffix) and same release name + type: string + values: + description: Values represents a collection of chart values. + type: object + nullable: true + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + description: ValuesFrom represents values from ConfigMap/Secret... + items: + description: ValuesFromSource represents a source of values, only + one of it's fields may be set + properties: + configMapKeyRef: + description: ConfigMapKeyRef selects a key of a ConfigMap + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key must + be defined + type: boolean + required: + - key + type: object + secretKeyRef: + description: SecretKeyRef selects a key of a Secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + type: array + version: + type: string + type: object + status: + properties: + conditions: + items: + properties: + lastProbeTime: + description: Last time we probed the condition. + format: date-time + type: string + nullable: true + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + nullable: true + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + description: 'Status is the status of the condition. Can be + True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: + description: 'Type is the type of the condition. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: object + type: array + lastSpecHash: + description: LastSpecHash store the has value of the synced spec, + if this value not equal to the current one, means we need to do + a update for the chart + type: string + notes: + description: Notes is the contents from helm (after helm install successfully + it will be printed to the console + type: string + phase: + description: HelmRequestPhase is a label for the condition of a HelmRequest + at the current time. + type: string + reason: + description: Reason will store the reason why the HelmRequest deploy + failed + type: string + syncedClusters: + description: SyncedClusters will store the synced clusters if InstallToAllClusters + is true + items: + type: string + type: array + version: + description: Verions is the real version that installed + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/charts/captain/values.yaml b/charts/captain/values.yaml index 8632aee7..a3bbe797 100644 --- a/charts/captain/values.yaml +++ b/charts/captain/values.yaml @@ -11,4 +11,4 @@ global: images: captain: repository: alaudapublic/captain - tag: v0.9.3 + tag: v1.5.0 diff --git a/config/crd/bases/chart.yaml b/config/crd/bases/chart.yaml index 8c1b393c..461cf969 100644 --- a/config/crd/bases/chart.yaml +++ b/config/crd/bases/chart.yaml @@ -1,23 +1,93 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: - name: charts.app.alauda.io + name: charts.app.alauda.io spec: - group: app.alauda.io - version: v1alpha1 - names: - kind: Chart - listKind: ChartList - plural: charts - singular: chart - additionalPrinterColumns: - - name: Version - type: string - JSONPath: .spec.versions[0].version - - name: AppVersion - type: string - JSONPath: .spec.versions[0].appVersion - - name: Age - type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced \ No newline at end of file + conversion: + strategy: None + group: app.alauda.io + names: + kind: Chart + listKind: ChartList + plural: charts + singular: chart + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version + type: string + - jsonPath: .spec.versions[0].appVersion + name: AppVersion + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - jsonPath: .spec.versions[0].version + name: Version + type: string + - jsonPath: .spec.versions[0].appVersion + name: AppVersion + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + versions: + items: + type: object + x-kubernetes-preserve-unknown-fields: true + type: array + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/config/crd/bases/chartrepo.yaml b/config/crd/bases/chartrepo.yaml index 47ab5347..4880a81f 100644 --- a/config/crd/bases/chartrepo.yaml +++ b/config/crd/bases/chartrepo.yaml @@ -1,36 +1,169 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: chartrepos.app.alauda.io annotations: "helm.sh/hook": crd-install spec: + conversion: + strategy: None group: app.alauda.io - version: v1alpha1 names: kind: ChartRepo listKind: ChartRepoList plural: chartrepos - singular: chartrepo shortNames: - - ctr - additionalPrinterColumns: - - name: URL + - ctr + singular: chartrepo + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL type: string - description: The url of this chart repo - JSONPath: .spec.url - - name: Phase + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase type: string - description: The phase of this ChartRepo - JSONPath: .status.phase - - name: Age + - jsonPath: .metadata.creationTimestamp + name: Age type: date - JSONPath: .metadata.creationTimestamp - scope: Namespaced - validation: - # openAPIV3Schema is the schema for validating custom objects. - openAPIV3Schema: - properties: - spec: - required: - - url \ No newline at end of file + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + url: + description: URL is the repo's url + type: string + required: + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: false + - additionalPrinterColumns: + - description: The url of this chart repo + jsonPath: .spec.url + name: URL + type: string + - description: The phase of this ChartRepo + jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + secret: + description: Secret contains information about how to auth to this + repo + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + nullable: true + type: object + source: + description: new in v1beta1.if type is Chart, this is optional and + it will provide some compatible with v1alpha1 + properties: + path: + description: may be root, may be a subdir + type: string + url: + description: vcs url + type: string + required: + - url + nullable: true + type: object + type: + description: new in v1beta1 + type: string + url: + description: URL is the repo's url + type: string + required: + - type + - url + type: object + status: + properties: + phase: + description: Phase ... After create, this phase will be updated to + indicate it's sync status If receive update event, and some field + in spec changed, sync agagin. + type: string + reason: + description: Reason is the failed reason + type: string + type: object + required: + - spec + type: object + served: true + storage: true diff --git a/config/crd/bases/crd.yaml b/config/crd/bases/crd.yaml index b8ff41c5..0c1beb5e 100644 --- a/config/crd/bases/crd.yaml +++ b/config/crd/bases/crd.yaml @@ -16,7 +16,7 @@ spec: - hrs scope: Namespaced versions: - - name: v1alpha1 + - name: v1 additionalPrinterColumns: - name: Chart type: string @@ -88,6 +88,37 @@ spec: multi clusters, we may have different HelmRequest name(with cluster prefix or suffix) and same release name type: string + source: + description: Source defines the source of chart, If this field is + set, Chart and Version field will be ignored(useless) + properties: + http: + properties: + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + url: + description: URL is the URL of the http(s) endpoint + type: string + required: + - url + type: object + oci: + properties: + repo: + description: Repo is the repo of the oci artifact + type: string + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + required: + - repo + type: object + type: object values: description: Values represents a collection of chart values. type: object @@ -206,4 +237,195 @@ spec: served: true storage: true subresources: - status: {} \ No newline at end of file + status: {} + - name: v1alpha1 + additionalPrinterColumns: + - name: Chart + type: string + description: The chart of this HelmRequest + jsonPath: .spec.chart + - name: Version + type: string + description: Version of this chart + jsonPath: .spec.version + - name: Namespace + type: string + description: The namespace which the chart deployed to + jsonPath: .spec.namespace + - name: AllCluster + type: boolean + description: Is this chart will be installed to all cluster + jsonPath: .spec.installToAllClusters + - name: Phase + type: string + description: The phase of this HelmRequest + jsonPath: .status.phase + - name: Age + type: date + jsonPath: .metadata.creationTimestamp + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + chart: + type: string + clusterName: + description: ClusterName is the cluster where the chart will be installed. + If InstallToAllClusters=true, this field will be ignored + type: string + dependencies: + description: Dependencies is the dependencies of this HelmRequest, + it's a list of there names THe dependencies must lives in the same + namespace, and each of them must be in Synced status before we sync + this HelmRequest + items: + type: string + type: array + installToAllClusters: + description: InstallToAllClusters will install this chart to all available + clusters, even the cluster was created after this chart. If this + field is true, ClusterName will be ignored(useless) + type: boolean + namespace: + description: Namespace is the namespace where the Release object will + be lived in. Notes this should be used with the values defined in + the chart, otherwise the install will failed + type: string + releaseName: + description: ReleaseName is the Release name to be generated, default + to HelmRequest.Name. If we want to manually install this chart to + multi clusters, we may have different HelmRequest name(with cluster + prefix or suffix) and same release name + type: string + values: + description: Values represents a collection of chart values. + type: object + nullable: true + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + description: ValuesFrom represents values from ConfigMap/Secret... + items: + description: ValuesFromSource represents a source of values, only + one of it's fields may be set + properties: + configMapKeyRef: + description: ConfigMapKeyRef selects a key of a ConfigMap + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key must + be defined + type: boolean + required: + - key + type: object + secretKeyRef: + description: SecretKeyRef selects a key of a Secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + type: array + version: + type: string + type: object + status: + properties: + conditions: + items: + properties: + lastProbeTime: + description: Last time we probed the condition. + format: date-time + type: string + nullable: true + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + nullable: true + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + description: 'Status is the status of the condition. Can be + True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: + description: 'Type is the type of the condition. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: object + type: array + lastSpecHash: + description: LastSpecHash store the has value of the synced spec, + if this value not equal to the current one, means we need to do + a update for the chart + type: string + notes: + description: Notes is the contents from helm (after helm install successfully + it will be printed to the console + type: string + phase: + description: HelmRequestPhase is a label for the condition of a HelmRequest + at the current time. + type: string + reason: + description: Reason will store the reason why the HelmRequest deploy + failed + type: string + syncedClusters: + description: SyncedClusters will store the synced clusters if InstallToAllClusters + is true + items: + type: string + type: array + version: + description: Verions is the real version that installed + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/controllers/chartrepo_controller.go b/controllers/chartrepo_controller.go index 56e1f758..7e01487e 100644 --- a/controllers/chartrepo_controller.go +++ b/controllers/chartrepo_controller.go @@ -38,7 +38,7 @@ import ( "helm.sh/helm/v3/pkg/repo" corev1 "k8s.io/api/core/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/apis/meta/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ctrl "sigs.k8s.io/controller-runtime" @@ -261,6 +261,8 @@ func (r *ChartRepoReconciler) buildChartRepoFromGit(ctx context.Context, cr *v1b if data == nil { data = map[string][]byte{} } + u := string(data["username"]) + p := string(data["password"]) var gr *git.Repository @@ -274,13 +276,15 @@ func (r *ChartRepoReconciler) buildChartRepoFromGit(ctx context.Context, cr *v1b if err != nil { return false, err } - err = w.Pull(&git.PullOptions{ - RemoteName: "origin", - Auth: &githttp.BasicAuth{ - Username: string(data["username"]), - Password: string(data["password"]), - }, - }) + + gpo := &git.PullOptions{RemoteName: "origin"} + if u != "" && p != "" { + gpo.Auth = &githttp.BasicAuth{ + Username: u, + Password: p, + } + } + err = w.Pull(gpo) if err != nil && err != git.NoErrAlreadyUpToDate { return false, err } @@ -288,14 +292,17 @@ func (r *ChartRepoReconciler) buildChartRepoFromGit(ctx context.Context, cr *v1b } else { log.Info("git clone source", "dir", dir, "url", cr.Spec.Source.URL) - g, err := git.PlainClone(dir, false, &git.CloneOptions{ - Auth: &githttp.BasicAuth{ - Username: string(data["username"]), - Password: string(data["password"]), - }, + gco := &git.CloneOptions{ URL: cr.Spec.Source.URL, Progress: os.Stdout, - }) + } + if u != "" && p != "" { + gco.Auth = &githttp.BasicAuth{ + Username: u, + Password: p, + } + } + g, err := git.PlainClone(dir, false, gco) if err != nil { return false, err } @@ -418,7 +425,7 @@ func getRepoIndexFile(req *http.Request) (*repo.IndexFile, error) { return loadIndex(body) } -// DownloadIndexFile fetches the index from a repository. +// GetIndex fetches the index from a repository. func (r *ChartRepoReconciler) GetIndex(cr *v1beta1.ChartRepo, ctx context.Context) (*repo.IndexFile, error) { var username string var password string diff --git a/docs/en/crd.md b/docs/en/crd.md index 20893834..bbe31185 100644 --- a/docs/en/crd.md +++ b/docs/en/crd.md @@ -13,6 +13,7 @@ - [spec.dependencies](#specdependencies) - [spec.values](#specvalues) - [spec.valuesFrom](#specvaluesfrom) + - [spec.source](#specsource) - [ChartRepo](#chartrepo) - [Basic Auth](#basic-auth) - [Type](#chartrepo-type) @@ -132,7 +133,43 @@ spec: Centralized configuration can be a great helper to manage multiple HelmRequest resources. +### spec.source +Helmrequest now supports version v1 and has added new fields. + +The chart's source. It's optional, this will indicate the source of the current chart, which will be an OCI or HTTP URL address. +If basic authentication is required, specify a secretname in the `spec.source.oci` or `spec.source.http`. + +As shown in the following examples + +```yaml +# OCI type +apiVersion: app.alauda.io/v1 +kind: HelmRequest +metadata: + name: test-oci + namespace: default +spec: + source: + oci: + repo: 192.168.26.40:60080/acp/chart-tomcat # oci repo address + secretRef: ociSecret # optional, if basic authentication is required, specify a secretname here. + values: + namespace: default + version: 9.2.9 # required, oci version +--- +# HTTP type +apiVersion: app.alauda.io/v1 +kind: HelmRequest +metadata: + name: test-http + namespace: default +spec: + source: + http: + url: https://alauda.github.io/captain-test-charts/wordpress-lookup-11.0.13.tgz + values: {} +``` ## ChartRepo diff --git a/docs/en/crds/helmrequest.md b/docs/en/crds/helmrequest.md index 34940178..18714dd9 100644 --- a/docs/en/crds/helmrequest.md +++ b/docs/en/crds/helmrequest.md @@ -107,10 +107,39 @@ spec: Centralized configuration can be a great helper to manage multiple HelmRequest resources. +## Helmrequest OCI support +now supports version v1 and has added new fields, as shown in the following examples +```yaml +# OCI type +apiVersion: app.alauda.io/v1 +kind: HelmRequest +metadata: + name: test-oci + namespace: default +spec: + source: + oci: + repo: 192.168.26.40:60080/acp/chart-tomcat # oci repo address + secretRef: ociSecret # optional, if basic authentication is required, specify a secretname here. + values: + namespace: default + version: 9.2.9 # required, oci version +--- +# HTTP type +apiVersion: app.alauda.io/v1 +kind: HelmRequest +metadata: + name: test-http + namespace: default +spec: + source: + http: + url: https://alauda.github.io/captain-test-charts/wordpress-lookup-11.0.13.tgz + values: {} +``` +## spec.source - - - - +The chart's source. It's optional, this will indicate the source of the current chart, which will be an OCI or HTTP URL address. +If basic authentication is required, specify a secretname in the `spec.source.oci` or `spec.source.http`. diff --git a/docs/zh/ano.md b/docs/zh/ano.md index 6b28203b..7af8d445 100644 --- a/docs/zh/ano.md +++ b/docs/zh/ano.md @@ -13,6 +13,22 @@ 在这种情况下,删除其中的任意一个`HelmRequest`都会删除相应的资源。 这个注解可以帮助你解决这个问题。(当然有一些方法可以安全地删除`HelmRequest`而不删除包含的资源) +## `captain-keep-resources` +适用于: `HelmRequest` + +可取值: True/False + +描述: + 如果你想在通过helm卸载chart时保留已部署的k8s资源,你可以使用这个注释告诉`Captain` ,这个HelmRequest对应的chart在进行卸载时将会保留资源。 + +## `captain-force-adopt-resources` +适用于: `HelmRequest` + +可取值: True/False + +描述: + 如果你想在通过helm安装或升级chart版本时领养k8s资源,你可以使用这个注释告诉`Captain`,这个HelmRequest将在安装或升级对应的chart时强制领养资源。因为在最新的helm版本中,不允许更新不属于当前release的同名资源。 + ## `kubectl-captain.resync` 适用于: `HelmRequest` @@ -29,4 +45,4 @@ 描述: 该注释标识`Captain`最后一次同步`ChartRepo`的时间。通常`chartrepos`会不时收到`Chart`更新,`Captain`定期从它的`index.yaml`中轮询更新。 - 这个时间戳可以向用户显示`Captain`是否正常工作。 \ No newline at end of file + 这个时间戳可以向用户显示`Captain`是否正常工作。 diff --git a/docs/zh/crds/helmrequest.md b/docs/zh/crds/helmrequest.md index ad0bffde..e6d546b8 100644 --- a/docs/zh/crds/helmrequest.md +++ b/docs/zh/crds/helmrequest.md @@ -104,4 +104,41 @@ spec: optional: true # optional; defaults to false ``` -集中配置可以成为管理多个 HelmRequest 资源的好帮手。 \ No newline at end of file +集中配置可以成为管理多个 HelmRequest 资源的好帮手。 + +## Helmrequest OCI support +现在支持v1版本,并添加了新的字段,如下面的示例所示 + +```yaml +# OCI type +apiVersion: app.alauda.io/v1 +kind: HelmRequest +metadata: + name: test-oci + namespace: default +spec: + source: + oci: + repo: 192.168.26.40:60080/acp/chart-tomcat # oci repo address + secretRef: ociSecret # optional, if basic authentication is required, specify a secretname here. + values: + namespace: default + version: 9.2.9 # required, oci version +--- +# HTTP type +apiVersion: app.alauda.io/v1 +kind: HelmRequest +metadata: + name: test-http + namespace: default +spec: + source: + http: + url: https://alauda.github.io/captain-test-charts/wordpress-lookup-11.0.13.tgz + values: {} +``` + +## spec.source + +spec.source 是可选项, 指示当前chart的源,它将是一个OCI或HTTP URL地址。 +如果需要基本身份验证, 在下面的字段中指定secret name即可: `spec.source.oci` or `spec.source.http`. diff --git a/go.mod b/go.mod index 5a49b26c..97660628 100644 --- a/go.mod +++ b/go.mod @@ -6,17 +6,17 @@ require ( github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/vcs v1.13.1 github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect - github.com/alauda/helm-crds v0.0.0-20210929080316-c14c5ae86a53 + github.com/alauda/helm-crds v0.0.0-20210914035428-6e2324c2b020 github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 github.com/bshuster-repo/logrus-logstash-hook v1.0.0 // indirect github.com/bugsnag/bugsnag-go v2.1.1+incompatible // indirect github.com/bugsnag/panicwrap v1.3.2 // indirect - github.com/containerd/containerd v1.4.13 + github.com/containerd/containerd v1.5.0-beta.1 + github.com/containers/image/v5 v5.11.0 github.com/davecgh/go-spew v1.1.1 github.com/deislabs/oras v0.11.1 - github.com/docker/go-metrics v0.0.1 // indirect + github.com/docker/cli v20.10.8+incompatible // indirect github.com/docker/go-units v0.4.0 - github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 // indirect github.com/garyburd/redigo v1.6.2 // indirect github.com/ghodss/yaml v1.0.0 github.com/go-logr/logr v0.4.0 @@ -30,7 +30,7 @@ require ( github.com/onsi/ginkgo v1.16.4 github.com/onsi/gomega v1.13.0 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.0.2 + github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 github.com/prometheus/common v0.26.0 @@ -59,14 +59,13 @@ require ( replace ( github.com/Masterminds/vcs => github.com/alauda/vcs v1.13.2-0.20200311111907-acd482b1ae9a - github.com/alauda/helm-crds => github.com/alauda/helm-crds v0.0.0-20210929080316-c14c5ae86a53 + github.com/alauda/helm-crds => github.com/alauda/helm-crds v0.0.0-20210914035428-6e2324c2b020 github.com/deislabs/oras => github.com/deislabs/oras v0.11.0 github.com/docker/distribution => github.com/distribution/distribution v2.7.1+incompatible github.com/docker/docker => github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309 github.com/go-logr/logr => github.com/go-logr/logr v0.4.0 github.com/go-logr/zapr => github.com/go-logr/zapr v0.4.0 github.com/miekg/dns => github.com/miekg/dns v1.0.0 - github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc95 github.com/xenolf/lego => github.com/go-acme/lego v0.4.0 helm.sh/helm/v3 => github.com/alauda/helm/v3 v3.6.4-0.20210914033728-4a2cde3ea69c diff --git a/go.sum b/go.sum index b64eee70..4ba1c0d6 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,7 @@ 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= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/14rcole/gopopulate v0.0.0-20180821133914-b175b219e774/go.mod h1:6/0dYRLLXyJjbkIPeeGyoJ/eKOSI0eU6eTlCBYibgd0= github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -58,14 +59,23 @@ github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmy github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Masterminds/squirrel v1.5.0 h1:JukIZisrUXadA9pl3rMkjhiamxiB0cXiu+HGp/Y8cY8= github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3 h1:mw6pDQqv38/WGF1cO/jF5t/jyAJ2yi7CmtFLLO5tGFI= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/Microsoft/hcsshim v0.8.10-0.20200715222032-5eafd1556990/go.mod h1:ay/0dTb7NsG8QMDfsRfLHgZo/6xAJShLe1+ePPflihk= -github.com/Microsoft/hcsshim v0.8.14 h1:lbPVK25c1cu5xTLITwpUcxoA9vKrKErASPYygvouJns= github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15 h1:Aof83YILRs2Vx3GhHqlvvfyx1asRJKMFIMeVlHsZKtI= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -78,14 +88,16 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/O github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alauda/component-base v0.0.0-20190628064654-a4dafcfd3446 h1:gtzuHCPURUuSWz5y/gkLQyxJn/W3pqG74YpzghVG7bY= github.com/alauda/component-base v0.0.0-20190628064654-a4dafcfd3446/go.mod h1:tbaXeIWDl6zX1b7O53FSXClDS1YmEDRnVJszgcLXzpk= -github.com/alauda/helm-crds v0.0.0-20210929080316-c14c5ae86a53 h1:RpFcr8P+//Y5GkxnUmjwuEHfawrxyE7LDZ5fmi23WVg= -github.com/alauda/helm-crds v0.0.0-20210929080316-c14c5ae86a53/go.mod h1:RwTIOTLbuiB67/CnG6lSwQcR2EpxPWv8h5KRHdvdCT4= +github.com/alauda/helm-crds v0.0.0-20210914035428-6e2324c2b020 h1:Geqd3ubOnwEUC/jm4PPLZbMCyfgDC0mw9fLD5IGAsyw= +github.com/alauda/helm-crds v0.0.0-20210914035428-6e2324c2b020/go.mod h1:RwTIOTLbuiB67/CnG6lSwQcR2EpxPWv8h5KRHdvdCT4= github.com/alauda/helm/v3 v3.6.4-0.20210914033728-4a2cde3ea69c h1:kHlh2kY6mHeBW46hPz43iGTAJ7rrUdrKug/bVBAbvGg= github.com/alauda/helm/v3 v3.6.4-0.20210914033728-4a2cde3ea69c/go.mod h1:mIIus8EOqj+obtycw3sidsR4ORr2aFDmXMSI3k+oeVY= github.com/alauda/vcs v1.13.2-0.20200311111907-acd482b1ae9a h1:tehWJjvfLunaJmmfcrxGP/1fPpASusJmLjm+RcP67Vc= @@ -99,6 +111,7 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= @@ -127,6 +140,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= @@ -134,6 +148,7 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v2.1.1+incompatible h1:tH4xLcWFBWTsri11ZSQnmPLVLn0IDvx9716veesAuW8= github.com/bugsnag/bugsnag-go v2.1.1+incompatible/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/panicwrap v1.3.2 h1:pNcbtPtH4Y6VwK+oZVNV/2H6Hh3jOL0ZNVFZEfd/eA4= @@ -148,49 +163,93 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= -github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/cheekybits/genny v0.0.0-20170328200008-9127e812e1e9/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/cilium/ebpf v0.5.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 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/container-storage-interface/spec v1.3.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102 h1:Qf4HiqfvmB7zS6scsmNgTLmByHbq8n9RTF39v+TzP7A= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.13 h1:Z0CbagVdn9VN4K6htOCY/jApSw8YKP+RdLZ5dkXF8PM= -github.com/containerd/containerd v1.4.13/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1 h1:IK6yirB4X7wpKyFSikWiT++nZsyIxGAAgNEv3fEGuls= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containers/image/v5 v5.11.0 h1:SwxGucW1AZ8H/5KH9jW70lo9WyuOrtxafutyQ9RPPLw= +github.com/containers/image/v5 v5.11.0/go.mod h1:dCbUB4w6gmxIEOCsE0tZQppr8iBoXb4Evr74ZKlmwoI= +github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= +github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0 h1:A6UzSUFMla92uxO43O6lm86i7evMGjTY7wTKB2DyGPY= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/storage v1.28.1 h1:axYBD+c0N0YkHelDoqzdLQXfY3fgb8pqIMsRHqUNGts= +github.com/containers/storage v1.28.1/go.mod h1:5bwiMh2LkrN3AWIfDFMH7A/xbVNLcve+oeXYvHvW8cc= github.com/coredns/corefile-migration v1.0.11/go.mod h1:RMy/mXdeDlYwzt0vdMEJvT2hGJ2I86/eO0UdXmH9XNI= 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/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 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/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.1/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/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= @@ -202,6 +261,10 @@ github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= 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= @@ -214,12 +277,15 @@ github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8 github.com/distribution/distribution v2.7.1+incompatible h1:aGFx4EvJWKEh//lHPLwFhFgwFHKH06TzNVPamrMn04M= github.com/distribution/distribution v2.7.1+incompatible/go.mod h1:EgLm2NgWtdKgzF9NpMzUKgzmR7AMmb0VQi2B+ZzDRjc= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v20.10.5+incompatible h1:bjflayQbWg+xOkF2WPEAOi4Y7zWhR7ptoPhV/VqLVDE= github.com/docker/cli v20.10.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v20.10.8+incompatible h1:/zO/6y9IOpcehE49yMRTV9ea0nBpb8OeqSskXLNfH1E= +github.com/docker/cli v20.10.8+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 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 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= @@ -241,7 +307,9 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= 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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= @@ -263,10 +331,10 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/garyburd/redigo v1.6.2 h1:yE/pwKCrbLpLpQICzYTeZ7JsTA/C53wFTJHaEtRqniM= github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= @@ -358,16 +426,21 @@ github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYi github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= 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.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 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= @@ -391,6 +464,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -413,6 +487,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= @@ -445,6 +520,7 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -465,11 +541,16 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= @@ -496,6 +577,8 @@ github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= @@ -503,6 +586,7 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ishidawataru/sctp v0.0.0-20190723014705-7c296d48a2b5/go.mod h1:DM4VvS+hD/kDi1U1QsX2fnZowwBhqD0Dk3bRPKF/Oc8= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= @@ -525,6 +609,7 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= @@ -537,15 +622,20 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW 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/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13 h1:eSvu8Tmq6j2psUJqJrLcWH6K3w5Dwc+qipbaA6eVEN4= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= 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/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 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/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= @@ -571,7 +661,9 @@ github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH github.com/lucas-clemente/quic-clients v0.1.0/go.mod h1:y5xVIEoObKqULIKivu+gD/LU90pL73bTdtQjPBvtCBk= github.com/lucas-clemente/quic-go v0.10.2/go.mod h1:hvaRS9IHjFLMq76puFJeWNfmn+H70QZ/CXoxqw9bzao= github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -580,6 +672,7 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -593,8 +686,10 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= @@ -604,6 +699,7 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= github.com/miekg/dns v1.0.0/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= @@ -629,7 +725,9 @@ github.com/moby/moby v0.7.3-0.20190826074503-38ab9da00309/go.mod h1:fDXVQ6+S340v github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1 h1:1O+1cHA1aujwEwwVMa2Xm2l+gIpUHyd3+D+d7LZh1kM= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk= github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -644,6 +742,7 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/mtrmac/gpgme v0.1.2/go.mod h1:GYYHnGSuS7HK3zVS2n3y73y0okK/BeKzwnn5jgiVFNI= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mvdan/xurls v1.1.0/go.mod h1:tQlNn3BED8bE/15hnSL2HLkDeLWpNPAwtw7wkEq44oU= @@ -671,15 +770,19 @@ github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:v github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -690,16 +793,27 @@ github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/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/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.0.0-rc95 h1:RMuWVfY3E1ILlVsC3RhIq38n4sJtlOFwU9gfFZSqrd0= -github.com/opencontainers/runc v1.0.0-rc95/go.mod h1:z+bZxa/+Tz/FmYVWkhUajJdzFeOqjc5vrqskhVyHGUM= +github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 h1:yN8BPXVwMBAm3Cuvh1L5XE8XpvYRMdsVLd82ILprhUU= +github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93 h1:x2UMpOOVf3kQ8arv/EsDGwim8PTNqzL1/EYDr/+scOM= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d h1:pNa8metDkwZjb9g4T8s+krQ+HRgZAkqnXml+wNir/+s= github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= 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= @@ -709,6 +823,7 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= 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/ostreedev/ostree-go v0.0.0-20190702140239-759a8c1ac913/go.mod h1:J6OG6YJVEWopen4avK3VNQSnALmmjvniMmni/YFYAwc= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= @@ -724,6 +839,7 @@ github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rK 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/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/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= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -732,6 +848,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= +github.com/pquerna/ffjson v0.0.0-20190813045741-dac163c6c0a9/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 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= @@ -764,6 +882,7 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/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.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -773,6 +892,9 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/quobyte/api v0.1.8/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/robfig/cron v1.1.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -788,6 +910,7 @@ github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNue 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= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -798,6 +921,8 @@ github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= 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= @@ -835,15 +960,18 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/storageos/go-api v2.2.0+incompatible/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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= @@ -852,7 +980,12 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tchap/go-patricia v2.3.0+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/teris-io/shortid v0.0.0-20160104014424-6c56cef5189c h1:MhdkG8ygXqjOGDouO0R1lIaXd4ZDMLhbO+rpzLmwe7Q= github.com/teris-io/shortid v0.0.0-20160104014424-6c56cef5189c/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0= github.com/thecodeteam/goscaleio v0.1.0/go.mod h1:68sdkZAsK8bvEwBlbQnlLS+xU+hvLYM/iQ8KXej1AwM= @@ -864,24 +997,34 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= +github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpcEPSzR8z6g= +github.com/vbauerster/mpb/v6 v6.0.3/go.mod h1:5luBx4rDLWxpA4t6I5sdeeQuZhqDxc+wr5Nqf35+tnM= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/ventu-io/go-shortid v0.0.0-20170305092000-935de6796a71 h1:A2guWvOfrSuNDtxVVMAPWUQBJhdmIibKcqOZhItazYY= github.com/ventu-io/go-shortid v0.0.0-20170305092000-935de6796a71/go.mod h1:6rZqAOk/eYX5FJyjQJ6Z3RBSN389IXX2ijwW4FcggaM= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b h1:6cLsL+2FW6dRAdl5iMtHgRogVCff0QpRi9653YmdcJA= +github.com/xeipuuv/gojsonpointer v0.0.0-20190809123943-df4f5c81cb3b/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -906,6 +1049,7 @@ go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3C 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= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -931,7 +1075,9 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -950,6 +1096,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= @@ -999,6 +1146,7 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r 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= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1029,6 +1177,7 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1047,6 +1196,7 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/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= @@ -1071,13 +1221,16 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w 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= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/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-20190812073006-9eafafc0a87e/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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1089,6 +1242,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -1096,6 +1250,7 @@ golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/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= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1104,17 +1259,22 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/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-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1228,6 +1388,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 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-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= 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= @@ -1256,10 +1417,14 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 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= @@ -1273,6 +1438,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba 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/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= 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= @@ -1285,6 +1451,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 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/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= @@ -1294,6 +1461,8 @@ gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm 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= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= @@ -1369,6 +1538,7 @@ k8s.io/kube-scheduler v0.21.1/go.mod h1:AFLD3tRlC0lbhB+WClraGOV/e5+NQyi5PeeL2CMK k8s.io/kubectl v0.21.1 h1:ySEusoeSgSDSiSBncDMsNrthSa3OSlXqT4R2rf1VFTw= k8s.io/kubectl v0.21.1/go.mod h1:PMYR88MqESuysBM/MX+Vu4JbX/50nY4d4kny+SPEI2U= k8s.io/kubelet v0.21.1/go.mod h1:poOR6Iaa5WqytFOp0egXFV8c2XTLFxaXTdj5njUlnVY= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/kubernetes v1.21.1 h1:U7cVOSdG+sMNOfL9XlenBV7avSBDHyWPE66gWnnYIIc= k8s.io/kubernetes v1.21.1/go.mod h1:ef++isEL1PW0taH6z7DXrSztPglrZ7jQhyvcMEtm0gQ= k8s.io/legacy-cloud-providers v0.21.1/go.mod h1:rpyWrAsPV1YNn7MmkZydMqleJijhay1Eqx+32K06Rd0= diff --git a/main.go b/main.go index 12002239..a325c640 100644 --- a/main.go +++ b/main.go @@ -32,6 +32,7 @@ import ( "github.com/alauda/captain/pkg/config" "github.com/alauda/captain/pkg/controller" "github.com/alauda/captain/pkg/webhook" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" appv1alpha1 "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" appv1beta1 "github.com/alauda/helm-crds/pkg/apis/app/v1beta1" corev1 "k8s.io/api/core/v1" @@ -43,6 +44,7 @@ import ( "k8s.io/klog" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" // +kubebuilder:scaffold:imports ) @@ -59,6 +61,7 @@ func init() { _ = appv1beta1.AddToScheme(scheme) + _ = appv1.AddToScheme(scheme) // +kubebuilder:scaffold:scheme } @@ -67,8 +70,10 @@ func main() { options.BindFlags() var metricsAddr string + var probeAddr string var enableLeaderElection bool flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "enable-leader-election", false, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") klog.InitFlags(nil) @@ -88,12 +93,13 @@ func main() { rp := time.Second * 120 mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - LeaderElection: enableLeaderElection, - LeaderElectionID: "captain-controller-lock", - Port: 9443, - SyncPeriod: &rp, + Scheme: scheme, + MetricsBindAddress: metricsAddr, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "captain-controller-lock", + Port: 9443, + SyncPeriod: &rp, }) if err != nil { setupLog.Error(err, "unable to start manager") @@ -187,6 +193,15 @@ func main() { http.ListenAndServe("0.0.0.0:6061", nil) }() + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up health check") + os.Exit(1) + } + if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { + setupLog.Error(err, "unable to set up ready check") + os.Exit(1) + } + setupLog.Info("starting manager") if err := mgr.Start(ctx); err != nil { setupLog.Error(err, "problem running manager") diff --git a/pkg/chartrepo/default.go b/pkg/chartrepo/default.go index ddaed259..23e7966b 100644 --- a/pkg/chartrepo/default.go +++ b/pkg/chartrepo/default.go @@ -2,9 +2,9 @@ package chartrepo import ( "context" - "github.com/alauda/helm-crds/pkg/apis/app/v1beta1" "time" + "github.com/alauda/helm-crds/pkg/apis/app/v1beta1" clientset "github.com/alauda/helm-crds/pkg/client/clientset/versioned" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/clusterregistry/apis/clusterregistry/v1alpha1/types.go b/pkg/clusterregistry/apis/clusterregistry/v1alpha1/types.go index a8dfe645..b487fe5c 100644 --- a/pkg/clusterregistry/apis/clusterregistry/v1alpha1/types.go +++ b/pkg/clusterregistry/apis/clusterregistry/v1alpha1/types.go @@ -17,7 +17,7 @@ limitations under the License. package v1alpha1 import ( - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/pkg/config/options.go b/pkg/config/options.go index 42696875..022ad910 100644 --- a/pkg/config/options.go +++ b/pkg/config/options.go @@ -2,6 +2,7 @@ package config import ( "flag" + "sigs.k8s.io/controller-runtime/pkg/manager" "github.com/alauda/captain/pkg/util" diff --git a/pkg/controller/clusterwatch.go b/pkg/controller/clusterwatch.go index 73552033..7f6063db 100644 --- a/pkg/controller/clusterwatch.go +++ b/pkg/controller/clusterwatch.go @@ -8,17 +8,16 @@ import ( "github.com/alauda/captain/pkg/cluster" "github.com/alauda/captain/pkg/util" - alpha1 "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" clientset "github.com/alauda/helm-crds/pkg/client/clientset/versioned" hrScheme "github.com/alauda/helm-crds/pkg/client/clientset/versioned/scheme" informers "github.com/alauda/helm-crds/pkg/client/informers/externalversions" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/kubernetes/typed/core/v1" + v1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" @@ -229,11 +228,8 @@ func (c *Controller) processNextClusterWorkItem(name string) bool { // Start the syncHandler, passing it the namespace/name string of the // HelmRequest resource to be synced. if err := c.syncHandler(key); err != nil { - // not rbac checked error - if !apierrors.IsForbidden(err) { - // Put the item back on the workQueue to handle any transient errors. - queue.AddRateLimited(key) - } + // Put the item back on the workQueue to handle any transient errors. + queue.AddRateLimited(key) return fmt.Errorf("error syncing '%s': %s, requeuing", key, err.Error()) } // Finally, if no error occurs we Forget this item so it does not @@ -292,7 +288,15 @@ func (c *Controller) deleteClusterHelmRequestHandler(obj interface{}, name strin return } - hr := obj.(*alpha1.HelmRequest) + hr, ok := obj.(*appv1.HelmRequest) + if !ok { + hr, err = convertToV1(obj) + if err != nil { + utilruntime.HandleError(err) + klog.Errorf("can not convert object to v1 helmrequest : %+v", obj) + return + } + } klog.Infof("receive delete event, cluster %s, : %+v", name, hr) hr = hr.DeepCopy() diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 73593557..4c5c997f 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -25,12 +25,12 @@ import ( "github.com/alauda/captain/pkg/config" "github.com/alauda/captain/pkg/helm" "github.com/alauda/captain/pkg/util" - alpha1 "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" clientset "github.com/alauda/helm-crds/pkg/client/clientset/versioned" informers "github.com/alauda/helm-crds/pkg/client/informers/externalversions" listers "github.com/alauda/helm-crds/pkg/client/listers/app/v1alpha1" commoncache "github.com/patrickmn/go-cache" - apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/kubernetes" @@ -169,7 +169,6 @@ func NewController(mgr manager.Manager, opt *config.Options, ctx context.Context // kubeInformerFactory.Start(stopCh) // appInformerFactory.Start(stopCh) - // fuck examples, this should after init controller appInformerFactory.Start(ctx.Done()) // chartRepoInformerFactory.Start(stopCh) @@ -205,17 +204,13 @@ func (c *Controller) Start(ctx context.Context) error { } klog.Info("Starting workers") - // Launch two workers to process HelmRequest resources - for i := 0; i < 2; i++ { - go wait.Until(c.runWorker, time.Second, ctx.Done()) - // go wait.Until(c.runChartRepoWorker, time.Second, stopCh) - } + go wait.Until(c.runWorker, time.Second, ctx.Done()) klog.Info("Started workers") <-ctx.Done() klog.Info("Shutting down workers") - // fuck. this bug. shutdown now manually + // shutdown now manually for _, v := range c.clusterWorkQueues { v.ShutDown() } @@ -267,11 +262,8 @@ func (c *Controller) processNextWorkItem() bool { // Start the syncHandler, passing it the namespace/name string of the // HelmRequest resource to be synced. if err := c.syncHandler(key); err != nil { - // not rbac checked error - if !apierrors.IsForbidden(err) { - // Put the item back on the workQueue to handle any transient errors. - c.workQueue.AddRateLimited(key) - } + // Put the item back on the workQueue to handle any transient errors. + c.workQueue.AddRateLimited(key) return fmt.Errorf("error syncing '%s': %s, requeuing", key, err.Error()) } // Finally, if no error occurs we Forget this item so it does not @@ -289,47 +281,77 @@ func (c *Controller) processNextWorkItem() bool { return true } -// see issue: https://github.com/kubernetes/kubernetes/issues/60845 -// the origin code in sample-controller is not working... fuck -func (c *Controller) updateHelmRequestStatus(helmRequest *alpha1.HelmRequest) error { +func (c *Controller) updateHelmRequestSynced(helmRequest *appv1.HelmRequest) error { + client := c.getAppClient(helmRequest) + origin, err := client.AppV1().HelmRequests(helmRequest.Namespace).Get(helmRequest.Name, metav1.GetOptions{}) + if err != nil { + return err + } + // NEVER modify objects from the store. It's a read-only, local cache. // You can use DeepCopy() to make a deep copy of original object and modify this copy // Or create a copy manually for better performance - h := helm.GenUniqueHash(helmRequest) + h := helm.GenUniqueHash(origin) // Note: we have to generate the hash before the deepcopy, because somehow the deepcopy // can create a spec that have different hash value. - request := helmRequest.DeepCopy() + request := origin.DeepCopy() + request.Status = *helmRequest.Status.DeepCopy() + request.Status.LastSpecHash = h request.Status.Reason = "" - request.Status.Phase = alpha1.HelmRequestSynced - return helm.UpdateHelmRequestStatus(c.getAppClient(helmRequest), request) + request.Status.Phase = appv1.HelmRequestSynced + + request.Status.Conditions = origin.Status.Conditions + return helm.UpdateHelmRequestStatus(client, request) } // setPartialSyncedStatus set spec hash and partial-synced status for helm-request -//TODO: merge with updateHelmRequestStatus -func (c *Controller) setPartialSyncedStatus(helmRequest *alpha1.HelmRequest) error { - h := helm.GenUniqueHash(helmRequest) - request := helmRequest.DeepCopy() +func (c *Controller) setPartialSyncedStatus(helmRequest *appv1.HelmRequest) error { + client := c.getAppClient(helmRequest) + origin, err := client.AppV1().HelmRequests(helmRequest.Namespace).Get(helmRequest.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + h := helm.GenUniqueHash(origin) + request := origin.DeepCopy() request.Status.LastSpecHash = h request.Status.Reason = "" - return c.updateHelmRequestPhase(request, alpha1.HelmRequestPartialSynced) + request.Status.Phase = appv1.HelmRequestPartialSynced + return helm.UpdateHelmRequestStatus(client, request) } // setSyncFailedStatus set HelmRequest to Failed and generated a warning event -func (c *Controller) setSyncFailedStatus(helmRequest *alpha1.HelmRequest, err error) error { +func (c *Controller) setSyncFailedStatus(helmRequest *appv1.HelmRequest, err error) error { c.sendFailedSyncEvent(helmRequest, err) - request := helmRequest.DeepCopy() + client := c.getAppClient(helmRequest) + origin, errI := client.AppV1().HelmRequests(helmRequest.Namespace).Get(helmRequest.Name, metav1.GetOptions{}) + if errI != nil { + return errI + } + + request := origin.DeepCopy() request.Status.Reason = err.Error() - return c.updateHelmRequestPhase(request, alpha1.HelmRequestFailed) + request.Status.Phase = appv1.HelmRequestFailed + return helm.UpdateHelmRequestStatus(client, request) } -func (c *Controller) setPendingStatus(helmRequest *alpha1.HelmRequest) error { - return c.updateHelmRequestPhase(helmRequest, alpha1.HelmRequestPending) +func (c *Controller) setPendingStatus(helmRequest *appv1.HelmRequest) error { + client := c.getAppClient(helmRequest) + origin, err := client.AppV1().HelmRequests(helmRequest.Namespace).Get(helmRequest.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + request := origin.DeepCopy() + request.Status.Phase = appv1.HelmRequestPending + request.Status.Reason = "" + return helm.UpdateHelmRequestStatus(client, request) } // getAppClient get a kubernetes app client for the target hr(may be from global cluster or other clusters) -func (c *Controller) getAppClient(hr *alpha1.HelmRequest) clientset.Interface { +func (c *Controller) getAppClient(hr *appv1.HelmRequest) clientset.Interface { if hr.ClusterName == "" { return c.appClientSet } @@ -347,7 +369,7 @@ func (c *Controller) getClusterAppClient(name string) clientset.Interface { } // if this helmrequst deployed to a remote cluster, the release cluster will be .spec.clusterName -func (c *Controller) getAppClientForRelease(hr *alpha1.HelmRequest) clientset.Interface { +func (c *Controller) getAppClientForRelease(hr *appv1.HelmRequest) clientset.Interface { if hr.Spec.ClusterName == "" { return c.getAppClient(hr) } @@ -367,7 +389,7 @@ func (c *Controller) getHelmRequestLister(name string) listers.HelmRequestLister return c.clusterHelmRequestListers[name] } -func (c *Controller) getEventRecorder(hr *alpha1.HelmRequest) record.EventRecorder { +func (c *Controller) getEventRecorder(hr *appv1.HelmRequest) record.EventRecorder { if hr.ClusterName == "" { return c.recorder } @@ -376,7 +398,7 @@ func (c *Controller) getEventRecorder(hr *alpha1.HelmRequest) record.EventRecord } // getDeployCluster returns the cluster name which the target Release lives in -func (c *Controller) getDeployCluster(hr *alpha1.HelmRequest) string { +func (c *Controller) getDeployCluster(hr *appv1.HelmRequest) string { if hr.Spec.ClusterName != "" { return hr.Spec.ClusterName } diff --git a/pkg/controller/dependency.go b/pkg/controller/dependency.go index 27ada5b5..94e4b599 100644 --- a/pkg/controller/dependency.go +++ b/pkg/controller/dependency.go @@ -3,15 +3,15 @@ package controller import ( "fmt" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/klog" ) // getHelmRequestDependencies get dependencies for a HelmRequest resource // If the target HelmRequest has no dependencies, return nil. Otherwise get the dependencies and return -func (c *Controller) getHelmRequestDependencies(hr *v1alpha1.HelmRequest) ([]*v1alpha1.HelmRequest, error) { - var data []*v1alpha1.HelmRequest +func (c *Controller) getHelmRequestDependencies(hr *appv1.HelmRequest) ([]*appv1.HelmRequest, error) { + var data []*appv1.HelmRequest deps := hr.Spec.Dependencies if len(deps) == 0 { klog.V(4).Infof("HelmRequest %s has no dependencies", hr.GetName()) @@ -20,7 +20,7 @@ func (c *Controller) getHelmRequestDependencies(hr *v1alpha1.HelmRequest) ([]*v1 cluster := c.getDeployCluster(hr) for _, name := range deps { - d, err := c.getClusterAppClient(cluster).AppV1alpha1().HelmRequests(hr.GetNamespace()).Get(name, metav1.GetOptions{}) + d, err := c.getClusterAppClient(cluster).AppV1().HelmRequests(hr.GetNamespace()).Get(name, metav1.GetOptions{}) if err != nil { klog.Errorf("Retrieve dependency %s for %s error: %s", name, hr.GetName(), err.Error()) return nil, err @@ -37,7 +37,7 @@ func (c *Controller) getHelmRequestDependencies(hr *v1alpha1.HelmRequest) ([]*v1 // go all the time. For more details please check: http://confluence.alaudatech.com/pages/viewpage.action?pageId=48729300 // If the check not pass or somethings goes wrong, return an error contains the detailed reson, this is // better than a bool var. -func (c *Controller) checkDependenciesForHelmRequest(hr *v1alpha1.HelmRequest) error { +func (c *Controller) checkDependenciesForHelmRequest(hr *appv1.HelmRequest) error { deps, err := c.getHelmRequestDependencies(hr) if err != nil { return err diff --git a/pkg/controller/event.go b/pkg/controller/event.go index b079f4b1..6a999fb1 100644 --- a/pkg/controller/event.go +++ b/pkg/controller/event.go @@ -3,7 +3,7 @@ package controller import ( "fmt" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" corev1 "k8s.io/api/core/v1" ) @@ -33,12 +33,12 @@ const ( ) // sendFailedDeleteEvent send a failed event when delete error -func (c *Controller) sendFailedDeleteEvent(hr *v1alpha1.HelmRequest, err error) { +func (c *Controller) sendFailedDeleteEvent(hr *appv1.HelmRequest, err error) { c.getEventRecorder(hr).Event(hr, corev1.EventTypeWarning, FailedDelete, fmt.Sprintf("Delete HelmRequest %s error : %s", hr.GetName(), err.Error())) } // sendFailedSyncEvent send a event when failed to sync a resource -func (c *Controller) sendFailedSyncEvent(hr *v1alpha1.HelmRequest, err error) { +func (c *Controller) sendFailedSyncEvent(hr *appv1.HelmRequest, err error) { c.getEventRecorder(hr).Event(hr, corev1.EventTypeWarning, FailedSync, err.Error()) } diff --git a/pkg/controller/eventhandler.go b/pkg/controller/eventhandler.go index 7cd875f4..9516adc5 100644 --- a/pkg/controller/eventhandler.go +++ b/pkg/controller/eventhandler.go @@ -1,9 +1,12 @@ package controller import ( + "encoding/json" "reflect" - alpha1 "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" + appv1alpha1 "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/tools/cache" "k8s.io/klog" ) @@ -13,8 +16,24 @@ import ( // obj at the same time func (c *Controller) newHelmRequestHandler() cache.ResourceEventHandler { updateFunc := func(old, new interface{}) { - oldHR := old.(*alpha1.HelmRequest) - newHR := new.(*alpha1.HelmRequest) + oldHR, ok := old.(*appv1.HelmRequest) + if !ok { + var err error + oldHR, err = convertToV1(old) + if err != nil { + klog.Errorf("can not convert object to v1 helmrequest : %+v", old) + return + } + } + newHR, ok := new.(*appv1.HelmRequest) + if !ok { + var err error + newHR, err = convertToV1(new) + if err != nil { + klog.Errorf("can not convert object to v1 helmrequest : %+v", new) + return + } + } // this is a bit of tricky // 1. old and new -> 1 cluster => check version and spec // 2. old and new -> N cluster => no check @@ -39,7 +58,7 @@ func (c *Controller) newHelmRequestHandler() cache.ResourceEventHandler { return } klog.V(4).Infof("old hr annotations: %+v, new hr annotations: %+v", oldHR.Annotations, newHR.Annotations) - klog.V(4).Infof("old hr: %+v, new hr: %+v", oldHR.Spec, newHR.Spec) + klog.V(4).Infof("old hr.spec: %+v, new hr.spec: %+v", oldHR.Spec, newHR.Spec) c.enqueueHelmRequest(new) } } @@ -58,8 +77,24 @@ func (c *Controller) newHelmRequestHandler() cache.ResourceEventHandler { // obj at the same time func (c *Controller) newClusterHelmRequestHandler(name string) cache.ResourceEventHandler { updateFunc := func(old, new interface{}) { - oldHR := old.(*alpha1.HelmRequest) - newHR := new.(*alpha1.HelmRequest) + oldHR, ok := old.(*appv1.HelmRequest) + if !ok { + var err error + oldHR, err = convertToV1(old) + if err != nil { + klog.Errorf("can not convert object to v1 helmrequest : %+v", old) + return + } + } + newHR, ok := new.(*appv1.HelmRequest) + if !ok { + var err error + newHR, err = convertToV1(new) + if err != nil { + klog.Errorf("can not convert object to v1 helmrequest : %+v", new) + return + } + } // this is a bit of tricky // 1. old and new -> 1 cluster => check version and spec // 2. old and new -> N cluster => no check @@ -75,7 +110,7 @@ func (c *Controller) newClusterHelmRequestHandler(name string) cache.ResourceEve c.enqueueClusterHelmRequest(new, name) } - if newHR.Status.Phase == alpha1.HelmRequestPending { + if newHR.Status.Phase == appv1.HelmRequestPending { klog.V(4).Infof("") } @@ -108,3 +143,25 @@ func (c *Controller) newClusterHelmRequestHandler(name string) cache.ResourceEve return funcs } + +func convertToV1(obj interface{}) (*appv1.HelmRequest, error) { + alphaHR := obj.(*appv1alpha1.HelmRequest) + gvk := schema.GroupVersionKind{ + Group: appv1.SchemeGroupVersion.Group, + Version: appv1.SchemeGroupVersion.Version, + Kind: alphaHR.GetObjectKind().GroupVersionKind().Kind, + } + alphaHR.SetGroupVersionKind(gvk) + + b, err := json.Marshal(alphaHR) + if err != nil { + return nil, err + } + + convertHR := &appv1.HelmRequest{} + if err := json.Unmarshal(b, convertHR); err != nil { + return nil, err + } + + return convertHR, nil +} diff --git a/pkg/controller/helmrequest.go b/pkg/controller/helmrequest.go index 385a5af2..d1af5d3e 100644 --- a/pkg/controller/helmrequest.go +++ b/pkg/controller/helmrequest.go @@ -7,11 +7,10 @@ import ( "github.com/alauda/captain/pkg/cluster" "github.com/alauda/captain/pkg/helm" "github.com/alauda/captain/pkg/util" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" "github.com/thoas/go-funk" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" @@ -39,7 +38,7 @@ func (c *Controller) syncHandler(key string) error { // Get the HelmRequest resource with this namespace/name // helmRequest, err := c.getHelmRequestLister(clusterName).HelmRequests(namespace).Get(name) - helmRequest, err := c.getClusterAppClient(clusterName).AppV1alpha1().HelmRequests(namespace).Get(name, metav1.GetOptions{}) + helmRequest, err := c.getClusterAppClient(clusterName).AppV1().HelmRequests(namespace).Get(name, metav1.GetOptions{}) if err != nil { // The HelmRequest resource may no longer exist, in which case we stop // processing. @@ -89,10 +88,11 @@ func (c *Controller) syncHandler(key string) error { if helm.IsHelmRequestSynced(helmRequest) { klog.Infof("HelmRequest %s synced", helmRequest.Name) - if helmRequest.Status.Phase != v1alpha1.HelmRequestSynced { + if helmRequest.Status.Phase != appv1.HelmRequestSynced { klog.Infof("helm request phase not synced, trying to set it") helmRequest.Status.Reason = "" - return c.updateHelmRequestPhase(helmRequest, v1alpha1.HelmRequestSynced) + helmRequest.Status.Phase = appv1.HelmRequestSynced + return helm.UpdateHelmRequestStatus(c.getAppClient(helmRequest), helmRequest) } return nil } @@ -113,7 +113,7 @@ func (c *Controller) syncHandler(key string) error { } // syncToCluster install/update HelmRequest to one cluster -func (c *Controller) syncToCluster(helmRequest *v1alpha1.HelmRequest) error { +func (c *Controller) syncToCluster(helmRequest *appv1.HelmRequest) error { clusterName := c.getDeployCluster(helmRequest) info, err := c.getClusterInfo(clusterName) if err != nil { @@ -129,7 +129,7 @@ func (c *Controller) syncToCluster(helmRequest *v1alpha1.HelmRequest) error { // Finally, we update the status block of the HelmRequest resource to reflect the // current state of the world - err = c.updateHelmRequestStatus(helmRequest) + err = c.updateHelmRequestSynced(helmRequest) return err } @@ -148,10 +148,10 @@ func (c *Controller) enqueueHelmRequest(obj interface{}) { // isOldEvent filters outdated event by compare resource uid // in case the resource not exist, we continue to real delete. -func (c *Controller) isOldEvent(cluster string, hr *v1alpha1.HelmRequest) (bool, error) { +func (c *Controller) isOldEvent(cluster string, hr *appv1.HelmRequest) (bool, error) { // Get the HelmRequest resource with this namespace/name // hr should have clusterName set. - current, err := c.getAppClient(hr).AppV1alpha1().HelmRequests(hr.Namespace).Get(hr.Name, metav1.GetOptions{}) + current, err := c.getAppClient(hr).AppV1().HelmRequests(hr.Namespace).Get(hr.Name, metav1.GetOptions{}) // don't want use the cached one. // current, err := c.getHelmRequestLister(cluster).HelmRequests(hr.Namespace).Get(hr.Name) if err != nil { @@ -195,7 +195,15 @@ func (c *Controller) deleteHandler(obj interface{}) { return } - hr := obj.(*v1alpha1.HelmRequest) + hr, ok := obj.(*appv1.HelmRequest) + if !ok { + hr, err = convertToV1(obj) + if err != nil { + runtime.HandleError(err) + klog.Errorf("can not convert object to v1 helmrequest : %+v", obj) + return + } + } klog.Infof("receive delete event: %+v", hr) @@ -222,9 +230,9 @@ func (c *Controller) deleteHandler(obj interface{}) { } } -// deleteHelmRequest delete the installed chart created by this HelmRequest +// deleteHelmRequest delete the installed chart created by this HelmRequest // if InstallToAllClusters=true, delete it from all clusters -func (c *Controller) deleteHelmRequest(hr *v1alpha1.HelmRequest) error { +func (c *Controller) deleteHelmRequest(hr *appv1.HelmRequest) error { // get clusters var clusters []*cluster.Info if hr.Spec.InstallToAllClusters { @@ -290,10 +298,10 @@ func (c *Controller) deleteHelmRequest(hr *v1alpha1.HelmRequest) error { // 1. support add finalizer for global/business clusters // 2. if there is and old hr without finalizer, compare uid of the event and only delete it if only the uid match // 3. hr should carry with cluster info -func (c *Controller) addFinalizer(hr *v1alpha1.HelmRequest) error { +func (c *Controller) addFinalizer(hr *appv1.HelmRequest) error { if !funk.Contains(hr.Finalizers, util.FinalizerName) { data := `{"metadata":{"finalizers":["captain.cpaas.io"]}}` - _, err := c.getAppClient(hr).AppV1alpha1().HelmRequests(hr.Namespace).Patch( + _, err := c.getAppClient(hr).AppV1().HelmRequests(hr.Namespace).Patch( hr.Name, types.MergePatchType, []byte(data), ) return err @@ -303,53 +311,16 @@ func (c *Controller) addFinalizer(hr *v1alpha1.HelmRequest) error { } // removeFinalizer remove all the finalizers of this HelmRequest -func (c *Controller) removeFinalizer(helmRequest *v1alpha1.HelmRequest) error { +func (c *Controller) removeFinalizer(helmRequest *appv1.HelmRequest) error { // captain.alauda.io is the old finalizer, this should provide some backword compatibility if funk.Contains(helmRequest.Finalizers, util.FinalizerName) || funk.Contains(helmRequest.Finalizers, "captain.alauda.io") { klog.Infof("found finalizers for helmrequest: %s", helmRequest.Name) data := `{"metadata":{"finalizers":null}}` // ? only patch can work? - _, err := c.getAppClient(helmRequest).AppV1alpha1().HelmRequests(helmRequest.Namespace).Patch( + _, err := c.getAppClient(helmRequest).AppV1().HelmRequests(helmRequest.Namespace).Patch( helmRequest.Name, types.MergePatchType, []byte(data), ) return err } return nil } - -// updateHelmRequestPhase update a helmrequest status -// If this helmrequest not exist already(delete by user, remove the release) -func (c *Controller) updateHelmRequestPhase(helmRequest *v1alpha1.HelmRequest, phase v1alpha1.HelmRequestPhase) error { - request := helmRequest.DeepCopy() - request.Status.Phase = phase - - client := c.getAppClient(helmRequest) - - // If the CustomResourceSubresources feature gate is not enabled, - // we must use Update instead of UpdateStatus to update the Status block of the HelmRequest resource. - // UpdateStatus will not allow changes to the Spec of the resource, - // which is ideal for ensuring nothing other than resource status has been updated. - _, err := client.AppV1alpha1().HelmRequests(helmRequest.Namespace).UpdateStatus(request) - if err != nil { - if apierrors.IsConflict(err) { - klog.Warning("update helm request status conflict, retry...") - origin, err := client.AppV1alpha1().HelmRequests(helmRequest.Namespace).Get(helmRequest.Name, metav1.GetOptions{}) - if err != nil { - if apierrors.IsNotFound(err) { - klog.Warning("helmrequest not found when trying to update status, delete the release...", helmRequest.Name) - return c.deleteHelmRequest(helmRequest) - } - return err - } - klog.Warningf("origin status: %+v, current: %+v", origin.Status, request.Status) - origin.Status = *request.Status.DeepCopy() - _, err = client.AppV1alpha1().HelmRequests(helmRequest.Namespace).UpdateStatus(origin) - if err != nil { - klog.Error("retrying update helmrequest status error:", err) - } - return err - } - klog.Errorf("update status for helmrequest %s error: %s", helmRequest.Name, err.Error()) - } - return err -} diff --git a/pkg/controller/sync.go b/pkg/controller/sync.go index a3a81f76..6eeca099 100644 --- a/pkg/controller/sync.go +++ b/pkg/controller/sync.go @@ -2,13 +2,13 @@ package controller import ( "fmt" - "github.com/pkg/errors" "os" "github.com/alauda/captain/pkg/cluster" "github.com/alauda/captain/pkg/helm" "github.com/alauda/captain/pkg/release" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" + "github.com/pkg/errors" "github.com/thoas/go-funk" helm_release "helm.sh/helm/v3/pkg/release" corev1 "k8s.io/api/core/v1" @@ -19,7 +19,7 @@ import ( ) // syncToAllClusters install/upgrade release in all the clusters -func (c *Controller) syncToAllClusters(key string, helmRequest *v1alpha1.HelmRequest) error { +func (c *Controller) syncToAllClusters(key string, helmRequest *appv1.HelmRequest) error { clusters, err := c.getAllClusters() if err != nil { return err @@ -32,7 +32,8 @@ func (c *Controller) syncToAllClusters(key string, helmRequest *v1alpha1.HelmReq // if not equal, we need to update helm status first if !equal { helmRequest.Status.SyncedClusters = make([]string, 0) - if err := c.updateHelmRequestPhase(helmRequest, v1alpha1.HelmRequestPending); err != nil { + helmRequest.Status.Phase = appv1.HelmRequestPending + if err := helm.UpdateHelmRequestStatus(c.getAppClient(helmRequest), helmRequest); err != nil { return err } } else if helmRequest.Status.SyncedClusters != nil { @@ -64,7 +65,7 @@ func (c *Controller) syncToAllClusters(key string, helmRequest *v1alpha1.HelmReq if len(synced) >= len(clusters) { // all synced - return c.updateHelmRequestStatus(helmRequest) + return c.updateHelmRequestSynced(helmRequest) } else if len(synced) > 0 { // partial synced c.sendFailedSyncEvent(helmRequest, err) @@ -74,7 +75,7 @@ func (c *Controller) syncToAllClusters(key string, helmRequest *v1alpha1.HelmReq } // sync install/update chart to one cluster -func (c *Controller) sync(info *cluster.Info, helmRequest *v1alpha1.HelmRequest) error { +func (c *Controller) sync(info *cluster.Info, helmRequest *appv1.HelmRequest) error { ci := *info ci.Namespace = helmRequest.GetReleaseNamespace() if err := release.EnsureCRDCreated(info.ToRestConfig()); err != nil { diff --git a/pkg/controller/sync_test.go b/pkg/controller/sync_test.go index 9aa7764d..6f96b098 100644 --- a/pkg/controller/sync_test.go +++ b/pkg/controller/sync_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/alauda/captain/pkg/helm" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" "github.com/ghodss/yaml" "github.com/gsamokovarov/assert" "helm.sh/helm/v3/pkg/chartutil" @@ -22,13 +22,13 @@ func TestHelmRequestDeepCopyHash(t *testing.T) { memory: 10m` var v chartutil.Values yaml.Unmarshal([]byte(values), &v) - hr := &v1alpha1.HelmRequest{ - Spec: v1alpha1.HelmRequestSpec{ + hr := &appv1.HelmRequest{ + Spec: appv1.HelmRequestSpec{ Chart: "stable/captain-test-demo", InstallToAllClusters: true, Namespace: "default", ReleaseName: "cpatain-test-demo", - HelmValues: v1alpha1.HelmValues{Values: v}, + HelmValues: appv1.HelmValues{Values: v}, Version: "1.2.1", }, } diff --git a/pkg/helm/common.go b/pkg/helm/common.go index a8dd1cfb..285ff5b4 100644 --- a/pkg/helm/common.go +++ b/pkg/helm/common.go @@ -6,11 +6,21 @@ import ( "hash/fnv" "github.com/alauda/captain/pkg/util" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" "github.com/davecgh/go-spew/spew" "helm.sh/helm/v3/pkg/helmpath" ) +type ChartSourceType string + +const ( + ChartSourceHTTP ChartSourceType = "http" + ChartSourceOCI ChartSourceType = "oci" + ChartSourceChart ChartSourceType = "chart" +) + +var systemUsers []string = []string{"admin", "kubernetes-admin"} + // DeepHashObject writes specified object to hash using the spew library // which follows pointers and prints actual values of the nested objects // ensuring the hash does not change when a pointer changes. @@ -40,9 +50,9 @@ func GenHashStr(data interface{}) string { } // GenUniqueHash generate a unique hash for a HelmRequest -func GenUniqueHash(hr *v1alpha1.HelmRequest) string { +func GenUniqueHash(hr *appv1.HelmRequest) string { source := struct { - spec v1alpha1.HelmRequestSpec + spec appv1.HelmRequestSpec annotations map[string]string }{ hr.Spec, @@ -55,7 +65,7 @@ func GenUniqueHash(hr *v1alpha1.HelmRequest) string { // only if hash is equal and not install to all clusters // First version: only hash .spec // Second version: hash .spec and .metadata.annotations -func IsHelmRequestSynced(hr *v1alpha1.HelmRequest) bool { +func IsHelmRequestSynced(hr *appv1.HelmRequest) bool { current := GenUniqueHash(hr) if current == hr.Status.LastSpecHash { return true @@ -74,7 +84,7 @@ func IsHelmRequestSynced(hr *v1alpha1.HelmRequest) bool { } // GetReleaseName get release name -func GetReleaseName(hr *v1alpha1.HelmRequest) string { +func GetReleaseName(hr *appv1.HelmRequest) string { return hr.GetReleaseName() } @@ -83,7 +93,7 @@ func helmRepositoryFile() string { } // isSwitchEnabled return annoKey Annotation is true or not -func isSwitchEnabled(hr *v1alpha1.HelmRequest, annoKey string) bool { +func isSwitchEnabled(hr *appv1.HelmRequest, annoKey string) bool { if hr == nil || len(hr.Annotations) == 0 { return false } @@ -94,3 +104,17 @@ func isSwitchEnabled(hr *v1alpha1.HelmRequest, annoKey string) bool { return false } + +func getChartSourceType(hr *appv1.HelmRequest) ChartSourceType { + if hr != nil && hr.Spec.Source != nil { + if hr.Spec.Source.HTTP != nil { + return ChartSourceHTTP + } + + if hr.Spec.Source.OCI != nil { + return ChartSourceOCI + } + } + + return ChartSourceChart +} diff --git a/pkg/helm/download.go b/pkg/helm/download.go index 2d70a4ae..bb71b21f 100644 --- a/pkg/helm/download.go +++ b/pkg/helm/download.go @@ -15,10 +15,13 @@ import ( "github.com/alauda/captain/pkg/chartrepo" "github.com/alauda/captain/pkg/registry" appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" + "github.com/containers/image/v5/docker" + "github.com/containers/image/v5/docker/reference" "github.com/go-logr/logr" "github.com/patrickmn/go-cache" "github.com/pkg/errors" "helm.sh/helm/v3/pkg/chart" + "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/repo" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -78,21 +81,21 @@ func (d *Downloader) getRepoInfo(name string, ns string) (*repo.Entry, error) { return entry, err } -// downloadChart download a chart from helm repo to local disk and return the path +// downloadChart download a chart from helm repo to local disk and return the chart // name: / -func (d *Downloader) downloadChart(name string, version string) (string, error) { +func (d *Downloader) downloadChart(name string, version string) (*chart.Chart, error) { log := d.log repoName, chart := getRepoAndChart(name) if repoName == "" && chart == "" { - return "", errors.New("cannot parse chart name") + return nil, errors.New("cannot parse chart name") } log.Info("get chart", "name", name, "version", version) dir := ChartsDir if _, err := os.Stat(dir); os.IsNotExist(err) { if err = os.MkdirAll(dir, 0755); err != nil { - return "", err + return nil, err } log.Info("helm charts dir not exist, create it: ", "dir", dir) } @@ -100,7 +103,7 @@ func (d *Downloader) downloadChart(name string, version string) (string, error) entry, err := d.getRepoInfo(repoName, d.ns) if err != nil { log.Error(err, "get chartrepo error") - return "", err + return nil, err } chartResourceName := fmt.Sprintf("%s.%s", strings.ToLower(chart), repoName) @@ -108,34 +111,26 @@ func (d *Downloader) downloadChart(name string, version string) (string, error) cv, err := chartrepo.GetChart(chartResourceName, version, d.ns, d.incfg) if err != nil { log.Error(err, "get chart error") - return "", err + return nil, err } path := cv.URLs[0] - fileName := strings.Split(path, "/")[1] + fileName := splitChartNameFromURL(path) filePath := fmt.Sprintf("%s/%s-%s-%s", dir, repoName, cv.Digest, fileName) if _, err := os.Stat(filePath); !os.IsNotExist(err) { log.Info("chart already downloaded, use it", "path", filePath) - return filePath, nil - } - - if err := downloadFileFromEntry(entry, path, filePath); err != nil { - log.Error(err, "download chart to disk error") - return "", err + return loader.Load(filePath) } - log.Info("download chart to disk", "path", filePath) - - return filePath, nil - + return loadFileFromEntry(entry, path, filePath) } -// downloadFileFromEntry will download a url and store it in local filepath. +// loadFileFromEntry will download a url and store it in local filepath. // It writes to the destination file as it downloads it, without // loading the entire file into memory. -func downloadFileFromEntry(entry *repo.Entry, chartPath, filepath string) error { +func loadFileFromEntry(entry *repo.Entry, chartPath, filePath string) (*chart.Chart, error) { ep := entry.URL + "/" + chartPath if strings.HasSuffix(entry.URL, "/") { ep = entry.URL + chartPath @@ -145,10 +140,10 @@ func downloadFileFromEntry(entry *repo.Entry, chartPath, filepath string) error ep = chartPath } - return downloadFile(ep, entry.Username, entry.Password, filepath) + return loadChart(ep, entry.Username, entry.Password, filePath) } -func downloadFile(url, username, password, filepath string) error { +func loadChart(url, username, password, filePath string) (*chart.Chart, error) { req, err := http.NewRequest("GET", url, nil) if username != "" && password != "" { req.SetBasicAuth(username, password) @@ -157,36 +152,35 @@ func downloadFile(url, username, password, filepath string) error { // Get the data resp, err := httpClient.Do(req) if err != nil { - return err + return nil, err } defer resp.Body.Close() if resp.StatusCode != 200 { - return errors.Errorf("failed to fetch %s : %s", url, resp.Status) + return nil, errors.Errorf("failed to fetch %s : %s", url, resp.Status) } buf := bytes.NewBuffer(nil) _, err = io.Copy(buf, resp.Body) if err != nil { - return err + return nil, err } - if err := ioutil.WriteFile(filepath, buf.Bytes(), 0644); err != nil { - return err + if err := ioutil.WriteFile(filePath, buf.Bytes(), 0644); err != nil { + return nil, err } - return nil + return loader.Load(filePath) } -func (d *Downloader) downloadChartFromHTTP(hr *appv1.HelmRequest) (string, error) { - var filePath string +func (d *Downloader) downloadChartFromHTTP(hr *appv1.HelmRequest) (*chart.Chart, error) { var err error if hr.Spec.Source != nil && hr.Spec.Source.HTTP != nil { if hr.Spec.Source.HTTP.URL != "" { dir := ChartsDir if _, err := os.Stat(dir); os.IsNotExist(err) { if err = os.MkdirAll(dir, 0755); err != nil { - return "", err + return nil, err } log.Info("helm charts dir not exist, create it: ", "dir", dir) } @@ -194,7 +188,7 @@ func (d *Downloader) downloadChartFromHTTP(hr *appv1.HelmRequest) (string, error url := hr.Spec.Source.HTTP.URL chname := splitChartNameFromURL(url) - filePath = fmt.Sprintf("%s/%s-%s", dir, hr.GetName(), chname) + filePath := fmt.Sprintf("%s/%s-%s", dir, hr.GetName(), chname) if _, err := os.Stat(filePath); !os.IsNotExist(err) { log.Info("chart already downloaded, remove it", "path", filePath) os.Remove(filePath) @@ -204,56 +198,39 @@ func (d *Downloader) downloadChartFromHTTP(hr *appv1.HelmRequest) (string, error if hr.Spec.Source.HTTP.SecretRef != "" { username, password, err = d.fetchAuthFromSecret(hr.Spec.Source.HTTP.SecretRef, hr.GetNamespace()) if err != nil { - return "", err + return nil, err } } if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - if err := downloadFile(url, username, password, filePath); err != nil { - return "", err - } - log.Info("successfully download chart from url", "url", url) - } else { - err = errors.New("helmrequest spec source http url does not start with HTTP or HTTPS") + return loadChart(url, username, password, filePath) } + err = errors.New("helmrequest spec source http url does not start with HTTP or HTTPS") } else { err = errors.New("helmrequest spec source http url not found") } } - return filePath, err + if err == nil { + err = errors.New("helmrequest spec source invalid, require HTTP type") + } + + return nil, err } func (d *Downloader) pullOCIChart(hr *appv1.HelmRequest) (*chart.Chart, error) { - client, err := registry.NewClient( - registry.ClientOptDebug(true), - ) - if err != nil { - return nil, err - } - if hr.Spec.Source != nil && hr.Spec.Source.OCI != nil { username, password := "", "" + var err error if hr.Spec.Source.OCI.SecretRef != "" { username, password, err = d.fetchAuthFromSecret(hr.Spec.Source.OCI.SecretRef, hr.GetNamespace()) if err != nil { return nil, err } } - ref, err := registry.ParseReference(hr.Spec.Source.OCI.Repo) - if err != nil { - return nil, err - } - if err := client.PullChart(ref, true, true, username, password); err != nil { - return nil, err - } - - cht, err := client.LoadChart(ref) - if err != nil { - return nil, err - } - return cht, nil + url := hr.Spec.Source.OCI.Repo + ":" + hr.Spec.Version + return d.pullAndLoadChart(url, username, password) } return nil, errors.New("invalid chart Source, need OCI type") @@ -311,3 +288,65 @@ func splitChartNameFromURL(url string) string { } return url[idx+1:] } + +func (d *Downloader) pullAndLoadChart(url, username, password string) (*chart.Chart, error) { + client, err := registry.NewClient( + registry.ClientOptDebug(true), + registry.ClientOptPlainHTTP(false), + ) + if err != nil { + return nil, err + } + + ref, err := registry.ParseReference(url) + if err != nil { + return nil, err + } + + domain := "" + if username != "" && password != "" { + tmpURL := url + if !strings.HasPrefix(tmpURL, "//") { + tmpURL = fmt.Sprintf("//%s", url) + } + imageRef, err := docker.ParseReference(tmpURL) + if err != nil { + d.log.Error(err, "could not parse image") + return nil, err + } + domain = reference.Domain(imageRef.DockerReference()) + if err := client.Login(domain, username, password, true); err != nil { + d.log.Error(err, "registry login error") + } + } + + buffer, err := client.PullChart(ref, true) + if err != nil { + if strings.Contains(err.Error(), "server gave HTTP response to HTTPS client") { + d.log.Info("Will try to pull chart again with plainHTTP", "response", err.Error()) + // set plainHTTP to true, and try to pull again + client2, err := registry.NewClient( + registry.ClientOptDebug(true), + registry.ClientOptPlainHTTP(true), + ) + if err != nil { + return nil, err + } + if domain != "" && username != "" && password != "" { + if err := client2.Login(domain, username, password, true); err != nil { + d.log.Error(err, "registry login error") + } + } + + buffer, err = client2.PullChart(ref, true) + if err != nil { + return nil, err + } + } else { + return nil, err + } + } + + d.log.Info("Pull chart successfully", "url", url) + return loader.LoadArchive(buffer) +} diff --git a/pkg/helm/status.go b/pkg/helm/status.go index 6a56b43a..9364b24a 100644 --- a/pkg/helm/status.go +++ b/pkg/helm/status.go @@ -3,7 +3,7 @@ package helm import ( "fmt" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" clientset "github.com/alauda/helm-crds/pkg/client/clientset/versioned" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -16,22 +16,22 @@ import ( // 1. no deletion helmrequest related resource when not found // 2. more simple // TODO: merge this two functions -func UpdateHelmRequestStatus(client clientset.Interface, request *v1alpha1.HelmRequest) error { +func UpdateHelmRequestStatus(client clientset.Interface, request *appv1.HelmRequest) error { // If the CustomResourceSubresources feature gate is not enabled, // we must use Update instead of UpdateStatus to update the Status block of the HelmRequest resource. // UpdateStatus will not allow changes to the Spec of the resource, // which is ideal for ensuring nothing other than resource status has been updated. - _, err := client.AppV1alpha1().HelmRequests(request.Namespace).UpdateStatus(request) + _, err := client.AppV1().HelmRequests(request.Namespace).UpdateStatus(request) if err != nil { if apierrors.IsConflict(err) { klog.Warning("update helm request status conflict, retry...") - origin, err := client.AppV1alpha1().HelmRequests(request.Namespace).Get(request.Name, metav1.GetOptions{}) + origin, err := client.AppV1().HelmRequests(request.Namespace).Get(request.Name, metav1.GetOptions{}) if err != nil { return err } klog.Warningf("origin status: %+v, current: %+v", origin.Status, request.Status) origin.Status = *request.Status.DeepCopy() - _, err = client.AppV1alpha1().HelmRequests(request.Namespace).UpdateStatus(origin) + _, err = client.AppV1().HelmRequests(request.Namespace).UpdateStatus(origin) if err != nil { klog.Error("retrying update helmrequest status error:", err) } @@ -44,16 +44,16 @@ func UpdateHelmRequestStatus(client clientset.Interface, request *v1alpha1.HelmR // AddConditionForHelmRequest ... // Note: this function will modify the hr object, this is not a good solution -func AddConditionForHelmRequest(condition *v1alpha1.HelmRequestCondition, hr *v1alpha1.HelmRequest, client clientset.Interface) error { - old, err := client.AppV1alpha1().HelmRequests(hr.Namespace).Get(hr.Name, metav1.GetOptions{}) +func AddConditionForHelmRequest(condition *appv1.HelmRequestCondition, hr *appv1.HelmRequest, client clientset.Interface) error { + old, err := client.AppV1().HelmRequests(hr.Namespace).Get(hr.Name, metav1.GetOptions{}) if err != nil { return err } conditions := old.Status.Conditions if len(conditions) == 0 { - conditions = []v1alpha1.HelmRequestCondition{*condition} + conditions = []appv1.HelmRequestCondition{*condition} } else { - var newConds []v1alpha1.HelmRequestCondition + var newConds []appv1.HelmRequestCondition added := false for _, item := range conditions { if item.Type == condition.Type { @@ -69,14 +69,14 @@ func AddConditionForHelmRequest(condition *v1alpha1.HelmRequestCondition, hr *v1 conditions = newConds } - hr.Status.Conditions = conditions - return UpdateHelmRequestStatus(client, hr) + old.Status.Conditions = conditions + return UpdateHelmRequestStatus(client, old) } -func newCondition(reason, message string, ty v1alpha1.HelmRequestConditionType, status v1.ConditionStatus) *v1alpha1.HelmRequestCondition { +func newCondition(reason, message string, ty appv1.HelmRequestConditionType, status v1.ConditionStatus) *appv1.HelmRequestCondition { t := metav1.Now() - return &v1alpha1.HelmRequestCondition{ + return &appv1.HelmRequestCondition{ LastTransitionTime: &t, Type: ty, Reason: reason, @@ -85,22 +85,12 @@ func newCondition(reason, message string, ty v1alpha1.HelmRequestConditionType, } } -func newChartLoadedCondition(chart string) *v1alpha1.HelmRequestCondition { - condition := newCondition("ChartLoaded", fmt.Sprintf("chart %s loaded", chart), v1alpha1.ConditionInitialized, v1.ConditionTrue) +func newChartLoadedCondition(chart string) *appv1.HelmRequestCondition { + condition := newCondition("ChartLoaded", fmt.Sprintf("chart %s loaded", chart), appv1.ConditionInitialized, v1.ConditionTrue) return condition } -func newRbacFailedCondition(message string) *v1alpha1.HelmRequestCondition { - cond := newCondition("PermissionCheckFailed", message, v1alpha1.ConditionValidated, v1.ConditionFalse) - return cond -} - -func newRbacPassedCondition() *v1alpha1.HelmRequestCondition { - cond := newCondition("PermissionCheckPassed", "current user permission check passed for chart resources", v1alpha1.ConditionValidated, v1.ConditionTrue) - return cond -} - -func (d *Deploy) addCondition(cond *v1alpha1.HelmRequestCondition) error { +func (d *Deploy) addCondition(cond *appv1.HelmRequestCondition) error { return AddConditionForHelmRequest(cond, d.HelmRequest, d.Client) } @@ -108,16 +98,3 @@ func (d *Deploy) setChartLoadedCondition(chart string) error { cond := newChartLoadedCondition(chart) return d.addCondition(cond) } - -// setRbacResultCondition check the err and add related conditions -func (d *Deploy) setRbacResultCondition(err error) error { - if err != nil { - // rbac checked error - if apierrors.IsForbidden(err) { - return d.addCondition(newRbacFailedCondition(err.Error())) - } - } - - // In all other cases, the RBAC check result of condition should set to passed - return d.addCondition(newRbacPassedCondition()) -} diff --git a/pkg/helm/sync.go b/pkg/helm/sync.go index 018548c9..ee17f4fa 100644 --- a/pkg/helm/sync.go +++ b/pkg/helm/sync.go @@ -9,7 +9,7 @@ import ( "github.com/alauda/captain/pkg/cluster" "github.com/alauda/captain/pkg/helmrequest" "github.com/alauda/captain/pkg/util" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" clientset "github.com/alauda/helm-crds/pkg/client/clientset/versioned" "github.com/go-logr/logr" "github.com/patrickmn/go-cache" @@ -17,7 +17,6 @@ import ( "github.com/teris-io/shortid" "helm.sh/helm/v3/pkg/action" "helm.sh/helm/v3/pkg/chart" - "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/storage" @@ -44,7 +43,7 @@ type Deploy struct { SystemNamespace string // all the charts info - HelmRequest *v1alpha1.HelmRequest + HelmRequest *appv1.HelmRequest // Client is the crd client for hr Client clientset.Interface @@ -132,15 +131,27 @@ func (d *Deploy) Sync() (*release.Release, error) { // load from cache first, then from disk var ch *chart.Chart downloader := NewDownloader(d.SystemNamespace, d.InCluster.ToRestConfig(), d.Cluster.ToRestConfig(), d.Log) - chartPath, err := downloader.downloadChart(hr.Spec.Chart, helmrequest.ResolveVersion(hr)) - if err != nil { - return nil, err - } - log.Info("load charts from disk", "path", chartPath) - ch, err = loader.Load(chartPath) - if err != nil { - log.Error(err, "failed to load chart from disk ", "path", chartPath) - return nil, err + switch getChartSourceType(hr) { + case ChartSourceChart: + ch, err = downloader.downloadChart(hr.Spec.Chart, helmrequest.ResolveVersion(hr)) + if err != nil { + log.Error(err, "failed to pull chart") + return nil, err + } + case ChartSourceOCI: + ch, err = downloader.pullOCIChart(hr) + if err != nil { + log.Error(err, "failed to pull oci chart") + return nil, err + } + case ChartSourceHTTP: + ch, err = downloader.downloadChartFromHTTP(hr) + if err != nil { + log.Error(err, "failed to pull http chart") + return nil, err + } + default: + return nil, errors.New("Unsupported chart source of helmrequest spec") } d.HelmRequest.Status.Version = ch.Metadata.Version diff --git a/pkg/helm/values.go b/pkg/helm/values.go index 9ab0b8b8..05da521a 100644 --- a/pkg/helm/values.go +++ b/pkg/helm/values.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" "github.com/ghodss/yaml" "helm.sh/helm/v3/pkg/chartutil" v1 "k8s.io/api/core/v1" @@ -47,7 +47,7 @@ func mergeValues(dest, src Values) Values { } // getValues merges all values settings from spec/configmap/secret... -func getValues(hr *v1alpha1.HelmRequest, cfg *rest.Config) (chartutil.Values, error) { +func getValues(hr *appv1.HelmRequest, cfg *rest.Config) (chartutil.Values, error) { values, err := getValuesFromSource(hr, cfg) if err != nil { return nil, err @@ -60,7 +60,7 @@ func getValues(hr *v1alpha1.HelmRequest, cfg *rest.Config) (chartutil.Values, er } -func getValuesFromSource(hr *v1alpha1.HelmRequest, cfg *rest.Config) (chartutil.Values, error) { +func getValuesFromSource(hr *appv1.HelmRequest, cfg *rest.Config) (chartutil.Values, error) { klog.V(2).Infof("in cluster rest config is: %+v", cfg) client, err := kubernetes.NewForConfig(cfg) if err != nil { diff --git a/pkg/helmrequest/types.go b/pkg/helmrequest/types.go index 16f48e0a..b215e55c 100644 --- a/pkg/helmrequest/types.go +++ b/pkg/helmrequest/types.go @@ -1,7 +1,7 @@ package helmrequest import ( - "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" ) var ( @@ -16,7 +16,7 @@ var ( // a. If annotations.auto-resolve-version-once=false, auto resolve version every time from chartrepo // b. If annotations.auto-resolve-version-once=true, auto resolve version in the first time, then use the version from // .status.verion -func ResolveVersion(hr *v1alpha1.HelmRequest) string { +func ResolveVersion(hr *appv1.HelmRequest) string { version := hr.Spec.Version if version != "" { return version diff --git a/pkg/helmrequest/yaml.go b/pkg/helmrequest/yaml.go index 0684d2ff..31e9a782 100644 --- a/pkg/helmrequest/yaml.go +++ b/pkg/helmrequest/yaml.go @@ -19,7 +19,7 @@ spec: - hrs scope: Namespaced versions: - - name: v1alpha1 + - name: v1 additionalPrinterColumns: - name: Chart type: string @@ -91,6 +91,37 @@ spec: multi clusters, we may have different HelmRequest name(with cluster prefix or suffix) and same release name type: string + source: + description: Source defines the source of chart, If this field is + set, Chart and Version field will be ignored(useless) + properties: + http: + properties: + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + url: + description: URL is the URL of the http(s) endpoint + type: string + required: + - url + type: object + oci: + properties: + repo: + description: Repo is the repo of the oci artifact + type: string + secretRef: + description: SecretRef A Secret reference, the secret should + contain accessKeyId (user name) base64 encoded, and secretKey + (password) also base64 encoded + type: string + required: + - repo + type: object + type: object values: description: Values represents a collection of chart values. type: object @@ -210,4 +241,195 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + additionalPrinterColumns: + - name: Chart + type: string + description: The chart of this HelmRequest + jsonPath: .spec.chart + - name: Version + type: string + description: Version of this chart + jsonPath: .spec.version + - name: Namespace + type: string + description: The namespace which the chart deployed to + jsonPath: .spec.namespace + - name: AllCluster + type: boolean + description: Is this chart will be installed to all cluster + jsonPath: .spec.installToAllClusters + - name: Phase + type: string + description: The phase of this HelmRequest + jsonPath: .status.phase + - name: Age + type: date + jsonPath: .metadata.creationTimestamp + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + chart: + type: string + clusterName: + description: ClusterName is the cluster where the chart will be installed. + If InstallToAllClusters=true, this field will be ignored + type: string + dependencies: + description: Dependencies is the dependencies of this HelmRequest, + it's a list of there names THe dependencies must lives in the same + namespace, and each of them must be in Synced status before we sync + this HelmRequest + items: + type: string + type: array + installToAllClusters: + description: InstallToAllClusters will install this chart to all available + clusters, even the cluster was created after this chart. If this + field is true, ClusterName will be ignored(useless) + type: boolean + namespace: + description: Namespace is the namespace where the Release object will + be lived in. Notes this should be used with the values defined in + the chart, otherwise the install will failed + type: string + releaseName: + description: ReleaseName is the Release name to be generated, default + to HelmRequest.Name. If we want to manually install this chart to + multi clusters, we may have different HelmRequest name(with cluster + prefix or suffix) and same release name + type: string + values: + description: Values represents a collection of chart values. + type: object + nullable: true + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + description: ValuesFrom represents values from ConfigMap/Secret... + items: + description: ValuesFromSource represents a source of values, only + one of it's fields may be set + properties: + configMapKeyRef: + description: ConfigMapKeyRef selects a key of a ConfigMap + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its key must + be defined + type: boolean + required: + - key + type: object + secretKeyRef: + description: SecretKeyRef selects a key of a Secret + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + type: object + type: array + version: + type: string + type: object + status: + properties: + conditions: + items: + properties: + lastProbeTime: + description: Last time we probed the condition. + format: date-time + type: string + nullable: true + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. + format: date-time + type: string + nullable: true + message: + description: Human-readable message indicating details about + last transition. + type: string + reason: + description: Unique, one-word, CamelCase reason for the condition's + last transition. + type: string + status: + description: 'Status is the status of the condition. Can be + True, False, Unknown. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: + description: 'Type is the type of the condition. More info: + https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions' + type: string + type: object + type: array + lastSpecHash: + description: LastSpecHash store the has value of the synced spec, + if this value not equal to the current one, means we need to do + a update for the chart + type: string + notes: + description: Notes is the contents from helm (after helm install successfully + it will be printed to the console + type: string + phase: + description: HelmRequestPhase is a label for the condition of a HelmRequest + at the current time. + type: string + reason: + description: Reason will store the reason why the HelmRequest deploy + failed + type: string + syncedClusters: + description: SyncedClusters will store the synced clusters if InstallToAllClusters + is true + items: + type: string + type: array + version: + description: Verions is the real version that installed + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} ` diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 19d80e19..9cbe33f1 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -14,6 +14,7 @@ limitations under the License. package registry // import "helm.sh/helm/v3/internal/experimental/registry" import ( + "bytes" "context" "crypto/tls" "fmt" @@ -24,8 +25,8 @@ import ( "strings" "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" auth "github.com/deislabs/oras/pkg/auth/docker" + "github.com/deislabs/oras/pkg/content" "github.com/deislabs/oras/pkg/oras" "github.com/gosuri/uitable" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -50,6 +51,7 @@ type ( authorizer *Authorizer resolver *Resolver cache *Cache + plainHTTP bool } ) @@ -75,7 +77,7 @@ func NewClient(opts ...ClientOption) (*Client, error) { } } if client.resolver == nil { - resolver, err := client.newResolver(true, true) + resolver, err := client.newResolver(true, client.plainHTTP) if err != nil { return nil, err } @@ -155,17 +157,66 @@ func (c *Client) PushChart(ref *Reference, insecure bool, plainHTTP bool) error } // PullChart downloads a chart from a registry -func (c *Client) PullChart(ref *Reference, insecure bool, plainHTTP bool, username, password string) error { - if username != "" && password != "" { - resolver, err := c.newAuthResolver(username, password, insecure, plainHTTP) - if err != nil { - return err - } - c.resolver = &Resolver{ - Resolver: resolver, +func (c *Client) PullChart(ref *Reference, insecure bool) (*bytes.Buffer, error) { + buf := bytes.NewBuffer(nil) + + if ref.Tag == "" { + return buf, errors.New("tag explicitly required") + } + + fmt.Fprintf(c.out, "%s: Pulling from %s\n", ref.Tag, ref.Repo) + + store := content.NewMemoryStore() + fullname := ref.FullName() + _ = fullname + _, layerDescriptors, err := oras.Pull(ctx(c.out, c.debug), c.resolver, ref.FullName(), store, + oras.WithPullEmptyNameAllowed(), + oras.WithAllowedMediaTypes(KnownMediaTypes())) + if err != nil { + return buf, err + } + + numLayers := len(layerDescriptors) + if numLayers < 1 { + return buf, errors.New( + fmt.Sprintf("manifest does not contain at least 1 layer (total: %d)", numLayers)) + } + + var contentLayer *ocispec.Descriptor + for _, layer := range layerDescriptors { + layer := layer + switch layer.MediaType { + case HelmChartContentLayerMediaType: + contentLayer = &layer + } } + if contentLayer == nil { + return buf, errors.New( + fmt.Sprintf("manifest does not contain a layer with mediatype %s", + HelmChartContentLayerMediaType)) + } + + _, b, ok := store.Get(*contentLayer) + if !ok { + return buf, errors.Errorf("Unable to retrieve blob with digest %s", contentLayer.Digest) + } + + buf = bytes.NewBuffer(b) + return buf, nil +} + +// PullChartToCache pulls a chart from an OCI Registry to the Registry Cache. +func (c *Client) PullChartToCache(ref *Reference, insecure bool, plainHTTP bool) error { + resolver, err := c.newResolver(insecure, plainHTTP) + if err != nil { + return err + } + c.resolver = &Resolver{ + Resolver: resolver, + } + if ref.Tag == "" { return errors.New("tag explicitly required") } @@ -179,10 +230,8 @@ func (c *Client) PullChart(ref *Reference, insecure bool, plainHTTP bool, userna oras.WithAllowedMediaTypes(KnownMediaTypes()), oras.WithContentProvideIngester(c.cache.ProvideIngester())) if err != nil { - if plainHTTP { - if strings.Contains(err.Error(), `\x15\x03\x01\x00\x02\x02`) { - return c.PullChart(ref, insecure, !plainHTTP, username, password) - } + if strings.Contains(err.Error(), "server gave HTTP response to HTTPS client") && (!plainHTTP) { + return c.PullChartToCache(ref, insecure, true) } return err } @@ -320,34 +369,3 @@ func (c *Client) newResolver(insecure bool, plainHTTP bool) (resolver remotes.Re resolver, err = c.authorizer.Resolver(context.Background(), client, plainHTTP) return } - -func (c *Client) newAuthResolver(username, password string, insecure bool, plainHTTP bool) (resolver remotes.Resolver, err error) { - opts := docker.ResolverOptions{ - PlainHTTP: plainHTTP, - } - - opts.Client = &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - InsecureSkipVerify: insecure, - }, - }, - } - - if username != "" || password != "" { - opts.Credentials = func(hostName string) (string, string, error) { - return username, password, nil - } - return docker.NewResolver(opts), nil - } - cli, err := auth.NewClient() - if err != nil { - fmt.Fprintf(c.out, "WARNING: Error loading auth file: %s", err.Error()) - } - resolver, err = cli.Resolver(context.Background(), opts.Client, plainHTTP) - if err != nil { - fmt.Fprintf(c.out, "WARNING: Error loading resolver: %s", err.Error()) - resolver = docker.NewResolver(opts) - } - return -} diff --git a/pkg/registry/client_opts.go b/pkg/registry/client_opts.go index e2f742ae..064c7dd2 100644 --- a/pkg/registry/client_opts.go +++ b/pkg/registry/client_opts.go @@ -33,6 +33,13 @@ func ClientOptDebug(debug bool) ClientOption { } } +// ClientOptPlainHTTP returns a function that sets the plainHTTP setting on client options set +func ClientOptPlainHTTP(plainHTTP bool) ClientOption { + return func(client *Client) { + client.plainHTTP = plainHTTP + } +} + // ClientOptWriter returns a function that sets the writer setting on client options set func ClientOptWriter(out io.Writer) ClientOption { return func(client *Client) { diff --git a/pkg/registry/client_test.go b/pkg/registry/client_test.go index 6c1f836b..9267a9ee 100644 --- a/pkg/registry/client_test.go +++ b/pkg/registry/client_test.go @@ -186,13 +186,13 @@ func (suite *RegistryClientTestSuite) Test_4_PullChart() { // non-existent ref ref, err := ParseReference(fmt.Sprintf("%s/testrepo/whodis:9.9.9", suite.DockerRegistryHost)) suite.Nil(err) - err = suite.RegistryClient.PullChart(ref, true, true, "", "") + _, err = suite.RegistryClient.PullChart(ref, true) suite.NotNil(err) // existing ref // ref, err = ParseReference(fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)) // suite.Nil(err) - // err = suite.RegistryClient.PullChart(ref, true, true, "", "") + // _, err = suite.RegistryClient.PullChart(ref, true) // suite.Nil(err) } @@ -229,7 +229,7 @@ func (suite *RegistryClientTestSuite) Test_8_ManInTheMiddle() { // suite.Nil(err) // returns content that does not match the expected digest - // err = suite.RegistryClient.PullChart(ref, true, true, "", "") + // _, err = suite.RegistryClient.PullChart(ref, true) // suite.NotNil(err) // suite.True(errdefs.IsFailedPrecondition(err)) } diff --git a/pkg/webhook/handler.go b/pkg/webhook/handler.go index e2fd5060..571d1a00 100644 --- a/pkg/webhook/handler.go +++ b/pkg/webhook/handler.go @@ -1,6 +1,7 @@ package webhook import ( + appv1 "github.com/alauda/helm-crds/pkg/apis/app/v1" "github.com/alauda/helm-crds/pkg/apis/app/v1alpha1" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -27,14 +28,14 @@ func RegisterHandlers(mgr manager.Manager) error { return err } - handler := admission.ValidatingWebhookFor(&v1alpha1.HelmRequest{}) + handler := admission.ValidatingWebhookFor(&appv1.HelmRequest{}) if err := handler.InjectLogger(log.Log.WithName("validating")); err != nil { wLog.Error(err, "inject logger to validating webhook handler error: ") return err } ws.Register("/validate", handler) - handler = admission.DefaultingWebhookFor(&v1alpha1.HelmRequest{}) + handler = admission.DefaultingWebhookFor(&appv1.HelmRequest{}) if err := handler.InjectLogger(log.Log.WithName("mutating")); err != nil { wLog.Error(err, "inject logger to mutating webhook handler error: ") return err