diff --git a/Dockerfile b/Dockerfile index d0a4c20797..e9375ba320 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,9 @@ COPY --from=builder /tmp/build/console /usr/bin/console # these manifests are necessary for the installer COPY manifests /manifests/ +# extensions manifests generated from openshift/api types +COPY vendor/github.com/openshift/api/console/v1/*.yaml /manifests + LABEL io.k8s.display-name="OpenShift console-operator" \ io.k8s.description="This is a component of OpenShift Container Platform and manages the lifecycle of the web console." \ io.openshift.tags="openshift" \ diff --git a/Dockerfile.rhel7 b/Dockerfile.rhel7 index 263e0d3d9b..f4535a0792 100644 --- a/Dockerfile.rhel7 +++ b/Dockerfile.rhel7 @@ -13,6 +13,9 @@ COPY --from=builder /tmp/build/console /usr/bin/console # these manifests are necessary for the installer COPY manifests /manifests/ +# extensions manifests generated from openshift/api types +COPY vendor/github.com/openshift/api/console/v1/*.yaml /manifests + LABEL io.k8s.display-name="OpenShift console-operator" \ io.k8s.description="This is a component of OpenShift Container Platform and manages the lifecycle of the web console." \ io.openshift.tags="openshift" \ diff --git a/glide.lock b/glide.lock index bfee9143c3..1709bb6d9c 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 66bf33dd9847c2a9505b6ed4718d2382a5eb0ffbd8bcf887bef4839b2add9485 -updated: 2019-10-01T13:09:11.533715+02:00 +updated: 2019-10-22T12:19:24.12769-04:00 imports: - name: github.com/beorn7/perks version: 3a771d992973f24aa725d07868b467d1ddfceafb @@ -133,7 +133,7 @@ imports: - name: github.com/NYTimes/gziphandler version: 56545f4a5d46df9a6648819d1664c3a03a13ffdb - name: github.com/openshift/api - version: d35a8e0fef2b28744b7034f0945a847f880f83ac + version: 82b963da83b3bfff4c4e9e4bb441c492f41d8da9 subpackages: - apps - apps/v1 @@ -176,10 +176,8 @@ imports: - template/v1 - user - user/v1 - - webconsole - - webconsole/v1 - name: github.com/openshift/client-go - version: 3b0e988f8cb09a07f375dfc304b86c1a81cbc82b + version: 2823239d2298214509c3536714f684101799e81b subpackages: - config/clientset/versioned - config/clientset/versioned/scheme @@ -217,7 +215,7 @@ imports: - route/informers/externalversions/route/v1 - route/listers/route/v1 - name: github.com/openshift/library-go - version: c355e2019bb35b1ae2b060208fdad8b488c28838 + version: a308f2050b153a206b2f98782cd152d924067026 subpackages: - pkg/config/client - pkg/config/clusteroperator/v1helpers @@ -273,9 +271,9 @@ imports: - name: github.com/sirupsen/logrus version: 839c75faf7f98a33d445d181f3018b5c3409a45e - name: github.com/spf13/cobra - version: 19cf35ea77e5981f8e8b90a897af621f2be864f6 + version: 67fc4837d267bc9bfd6e47f77783fcc3dffc68de - name: github.com/spf13/pflag - version: 2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab + version: 298182f68c66c05229eb03ac171abe6e309ee79a - name: go.uber.org/atomic version: 8dc6146f7569370a472715e178d8ae31172ee6da - name: go.uber.org/multierr @@ -340,7 +338,7 @@ imports: subpackages: - rate - name: golang.org/x/tools - version: 7c411dea38b0106295d041581abb0a958e571b7d + version: e65039ee4138194d75ebaa2da35887260d5e15b2 subpackages: - imports - name: google.golang.org/appengine diff --git a/pkg/console/controllers/clidownloads/controller.go b/pkg/console/controllers/clidownloads/controller.go index 0df4cedeb7..b10410b12b 100644 --- a/pkg/console/controllers/clidownloads/controller.go +++ b/pkg/console/controllers/clidownloads/controller.go @@ -165,9 +165,9 @@ func PlatformBasedOCConsoleCLIDownloads(host, arch, cliDownloadsName string) *v1 {"Windows", "windows", "oc.zip"}, } - links := []v1.Link{} + links := []v1.CLIDownloadLink{} for _, platform := range platforms { - links = append(links, v1.Link{ + links = append(links, v1.CLIDownloadLink{ Href: GetPlatformURL(baseURL, platform.key, platform.archType), Text: fmt.Sprintf("Download oc for %s", platform.label), }) @@ -199,7 +199,7 @@ func ODOConsoleCLIDownloads() *v1.ConsoleCLIDownload { odo abstracts away complex Kubernetes and OpenShift concepts, thus allowing developers to focus on what is most important to them: code. `, DisplayName: "odo - Developer-focused CLI for OpenShift", - Links: []v1.Link{ + Links: []v1.CLIDownloadLink{ { Href: "https://mirror.openshift.com/pub/openshift-v4/clients/odo/latest/", Text: "Download odo", diff --git a/pkg/console/controllers/clidownloads/controller_test.go b/pkg/console/controllers/clidownloads/controller_test.go index 8cfbca1c24..d68b1aee64 100644 --- a/pkg/console/controllers/clidownloads/controller_test.go +++ b/pkg/console/controllers/clidownloads/controller_test.go @@ -84,7 +84,7 @@ func TestPlatformBasedOCConsoleCLIDownloads(t *testing.T) { The oc binary offers the same capabilities as the kubectl binary, but it is further extended to natively support OpenShift Container Platform features. `, DisplayName: "oc - OpenShift Command Line Interface (CLI)", - Links: []v1.Link{ + Links: []v1.CLIDownloadLink{ { Href: "https://www.example.com/amd64/linux/oc.tar", Text: "Download oc for Linux", diff --git a/vendor/github.com/openshift/api/.travis.yml b/vendor/github.com/openshift/api/.travis.yml index 494d91ee48..d67d8be646 100644 --- a/vendor/github.com/openshift/api/.travis.yml +++ b/vendor/github.com/openshift/api/.travis.yml @@ -1,7 +1,7 @@ language: go go: - - "1.11" + - "1.12" install: - wget https://github.com/google/protobuf/releases/download/v3.0.2/protoc-3.0.2-linux-x86_64.zip diff --git a/vendor/github.com/openshift/api/Makefile b/vendor/github.com/openshift/api/Makefile index ba83ccb143..4c2919bb83 100644 --- a/vendor/github.com/openshift/api/Makefile +++ b/vendor/github.com/openshift/api/Makefile @@ -1,33 +1,49 @@ all: build .PHONY: all -RUNTIME ?= podman -RUNTIME_IMAGE_NAME ?= openshift-api-generator +# Include the library makefile +include $(addprefix ./hack/alpha-build-machinery/make/, \ + golang.mk \ + targets/openshift/deps.mk \ + targets/openshift/crd-schema-gen.mk \ +) + +GO_PACKAGES :=$(addsuffix ...,$(addprefix ./,$(filter-out vendor/,$(filter-out hack/,$(wildcard */))))) +GO_BUILD_PACKAGES :=$(GO_PACKAGES) +GO_BUILD_PACKAGES_EXPANDED :=$(GO_BUILD_PACKAGES) +# LDFLAGS are not needed for dummy builds (saving time on calling git commands) +GO_LD_FLAGS:= -build: - go build github.com/openshift/api/... -.PHONY: build +# $1 - target name +# $2 - apis +# $3 - manifests +# $4 - output +$(call add-crd-gen,authorization,./authorization/v1,./authorization/v1,./authorization/v1) +$(call add-crd-gen,config,./config/v1,./config/v1,./config/v1) +$(call add-crd-gen,console,./console/v1,./console/v1,./console/v1) +$(call add-crd-gen,operator,./operator/v1,./operator/v1,./operator/v1) +$(call add-crd-gen,operator-alpha,./operator/v1alpha1,./operator/v1alpha1,./operator/v1alpha1) +$(call add-crd-gen,quota,./quota/v1,./quota/v1,./quota/v1) +$(call add-crd-gen,security,./security/v1,./security/v1,./security/v1) -test: - go test github.com/openshift/api/... -.PHONY: test +RUNTIME ?= podman +RUNTIME_IMAGE_NAME ?= openshift-api-generator -verify: +verify-scripts: bash -x hack/verify-deepcopy.sh bash -x hack/verify-protobuf.sh bash -x hack/verify-swagger-docs.sh -.PHONY: verify - -update-deps: - hack/update-deps.sh -.PHONY: update-deps + bash -x hack/verify-crds.sh +.PHONY: verify-scripts +verify: verify-scripts -generate-with-container: Dockerfile.build - $(RUNTIME) build -t $(RUNTIME_IMAGE_NAME) -f Dockerfile.build . - $(RUNTIME) run -ti --rm -v $(PWD):/go/src/github.com/openshift/api:z -w /go/src/github.com/openshift/api $(RUNTIME_IMAGE_NAME) make generate - -generate: +update-scripts: hack/update-deepcopy.sh hack/update-protobuf.sh hack/update-swagger-docs.sh -.PHONY: generate +.PHONY: update-scripts +update: update-scripts + +generate-with-container: Dockerfile.build + $(RUNTIME) build -t $(RUNTIME_IMAGE_NAME) -f Dockerfile.build . + $(RUNTIME) run -ti --rm -v $(PWD):/go/src/github.com/openshift/api:z -w /go/src/github.com/openshift/api $(RUNTIME_IMAGE_NAME) make update-scripts diff --git a/vendor/github.com/openshift/api/apps/v1/generated.proto b/vendor/github.com/openshift/api/apps/v1/generated.proto index 21d2202e04..b412aad765 100644 --- a/vendor/github.com/openshift/api/apps/v1/generated.proto +++ b/vendor/github.com/openshift/api/apps/v1/generated.proto @@ -73,7 +73,6 @@ message DeploymentCondition { // is carried out and may be changed at any time. The `latestVersion` field is updated when a new deployment // is triggered by any means. message DeploymentConfig { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Spec represents a desired deployment state and how to deploy to it. @@ -85,7 +84,6 @@ message DeploymentConfig { // DeploymentConfigList is a collection of deployment configs. message DeploymentConfigList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of deployment configs diff --git a/vendor/github.com/openshift/api/apps/v1/types.go b/vendor/github.com/openshift/api/apps/v1/types.go index f3ba06191d..02e0398494 100644 --- a/vendor/github.com/openshift/api/apps/v1/types.go +++ b/vendor/github.com/openshift/api/apps/v1/types.go @@ -25,8 +25,7 @@ import ( // is carried out and may be changed at any time. The `latestVersion` field is updated when a new deployment // is triggered by any means. type DeploymentConfig struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Spec represents a desired deployment state and how to deploy to it. @@ -389,7 +388,6 @@ type DeploymentCondition struct { // DeploymentConfigList is a collection of deployment configs. type DeploymentConfigList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of deployment configs diff --git a/vendor/github.com/openshift/api/apps/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/apps/v1/zz_generated.swagger_doc_generated.go index f8ec2bd1dd..9e3a07e8f9 100644 --- a/vendor/github.com/openshift/api/apps/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/apps/v1/zz_generated.swagger_doc_generated.go @@ -56,10 +56,9 @@ func (DeploymentCondition) SwaggerDoc() map[string]string { } var map_DeploymentConfig = map[string]string{ - "": "Deployment Configs define the template for a pod and manages deploying new images or configuration changes. A single deployment configuration is usually analogous to a single micro-service. Can support many different deployment patterns, including full restart, customizable rolling updates, and fully custom behaviors, as well as pre- and post- deployment hooks. Each individual deployment is represented as a replication controller.\n\nA deployment is \"triggered\" when its configuration is changed or a tag in an Image Stream is changed. Triggers can be disabled to allow manual control over a deployment. The \"strategy\" determines how the deployment is carried out and may be changed at any time. The `latestVersion` field is updated when a new deployment is triggered by any means.", - "metadata": "Standard object's metadata.", - "spec": "Spec represents a desired deployment state and how to deploy to it.", - "status": "Status represents the current deployment state.", + "": "Deployment Configs define the template for a pod and manages deploying new images or configuration changes. A single deployment configuration is usually analogous to a single micro-service. Can support many different deployment patterns, including full restart, customizable rolling updates, and fully custom behaviors, as well as pre- and post- deployment hooks. Each individual deployment is represented as a replication controller.\n\nA deployment is \"triggered\" when its configuration is changed or a tag in an Image Stream is changed. Triggers can be disabled to allow manual control over a deployment. The \"strategy\" determines how the deployment is carried out and may be changed at any time. The `latestVersion` field is updated when a new deployment is triggered by any means.", + "spec": "Spec represents a desired deployment state and how to deploy to it.", + "status": "Status represents the current deployment state.", } func (DeploymentConfig) SwaggerDoc() map[string]string { @@ -67,9 +66,8 @@ func (DeploymentConfig) SwaggerDoc() map[string]string { } var map_DeploymentConfigList = map[string]string{ - "": "DeploymentConfigList is a collection of deployment configs.", - "metadata": "Standard object's metadata.", - "items": "Items is a list of deployment configs", + "": "DeploymentConfigList is a collection of deployment configs.", + "items": "Items is a list of deployment configs", } func (DeploymentConfigList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/authorization/OWNERS b/vendor/github.com/openshift/api/authorization/OWNERS deleted file mode 100644 index f0e98440ac..0000000000 --- a/vendor/github.com/openshift/api/authorization/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -reviewers: - - enj diff --git a/vendor/github.com/openshift/api/authorization/v1/0000_03_authorization-openshift_01_rolebindingrestriction.crd.yaml b/vendor/github.com/openshift/api/authorization/v1/0000_03_authorization-openshift_01_rolebindingrestriction.crd.yaml new file mode 100644 index 0000000000..028ce1db16 --- /dev/null +++ b/vendor/github.com/openshift/api/authorization/v1/0000_03_authorization-openshift_01_rolebindingrestriction.crd.yaml @@ -0,0 +1,205 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: rolebindingrestrictions.authorization.openshift.io +spec: + group: authorization.openshift.io + names: + kind: RoleBindingRestriction + listKind: RoleBindingRestrictionList + plural: rolebindingrestrictions + singular: rolebindingrestriction + scope: Namespaced + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: RoleBindingRestriction is an object that can be matched against + a subject (user, group, or service account) to determine whether rolebindings + on that subject are allowed in the namespace to which the RoleBindingRestriction + belongs. If any one of those RoleBindingRestriction objects matches a subject, + rolebindings on that subject in the namespace are allowed. + type: object + 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: + description: Spec defines the matcher. + type: object + properties: + grouprestriction: + description: GroupRestriction matches against group subjects. + type: object + properties: + groups: + description: Groups is a list of groups used to match against an + individual user's groups. If the user is a member of one of the + whitelisted groups, the user is allowed to be bound to a role. + type: array + items: + type: string + nullable: true + labels: + description: Selectors specifies a list of label selectors over + group labels. + type: array + items: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An + empty label selector matches all objects. A null label selector + matches no objects. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + nullable: true + nullable: true + serviceaccountrestriction: + description: ServiceAccountRestriction matches against service-account + subjects. + type: object + properties: + namespaces: + description: Namespaces specifies a list of literal namespace names. + type: array + items: + type: string + serviceaccounts: + description: ServiceAccounts specifies a list of literal service-account + names. + type: array + items: + description: ServiceAccountReference specifies a service account + and namespace by their names. + type: object + properties: + name: + description: Name is the name of the service account. + type: string + namespace: + description: Namespace is the namespace of the service account. Service + accounts from inside the whitelisted namespaces are allowed + to be bound to roles. If Namespace is empty, then the namespace + of the RoleBindingRestriction in which the ServiceAccountReference + is embedded is used. + type: string + nullable: true + userrestriction: + description: UserRestriction matches against user subjects. + type: object + properties: + groups: + description: Groups specifies a list of literal group names. + type: array + items: + type: string + nullable: true + labels: + description: Selectors specifies a list of label selectors over + user labels. + type: array + items: + description: A label selector is a label query over a set of resources. + The result of matchLabels and matchExpressions are ANDed. An + empty label selector matches all objects. A null label selector + matches no objects. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. + type: object + additionalProperties: + type: string + nullable: true + users: + description: Users specifies a list of literal user names. + type: array + items: + type: string + nullable: true diff --git a/vendor/github.com/openshift/api/authorization/v1/generated.proto b/vendor/github.com/openshift/api/authorization/v1/generated.proto index 9816838461..d43b737185 100644 --- a/vendor/github.com/openshift/api/authorization/v1/generated.proto +++ b/vendor/github.com/openshift/api/authorization/v1/generated.proto @@ -43,12 +43,12 @@ message Action { optional bool isNonResourceURL = 9; // Content is the actual content of the request for create and update + // +kubebuilder:validation:PreserveUnknownFields optional k8s.io.apimachinery.pkg.runtime.RawExtension content = 7; } // ClusterRole is a logical grouping of PolicyRules that can be referenced as a unit by ClusterRoleBindings. message ClusterRole { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Rules holds all the PolicyRules for this ClusterRole @@ -64,7 +64,6 @@ message ClusterRole { // It adds who information via (Users and Groups) OR Subjects and namespace information by which namespace it exists in. // ClusterRoleBindings in a given namespace only have effect in that namespace (excepting the master namespace which has power in all namespaces). message ClusterRoleBinding { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // UserNames holds all the usernames directly bound to the role. @@ -94,7 +93,6 @@ message ClusterRoleBinding { // ClusterRoleBindingList is a collection of ClusterRoleBindings message ClusterRoleBindingList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of ClusterRoleBindings @@ -103,7 +101,6 @@ message ClusterRoleBindingList { // ClusterRoleList is a collection of ClusterRoles message ClusterRoleList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of ClusterRoles @@ -215,6 +212,7 @@ message PolicyRule { // AttributeRestrictions will vary depending on what the Authorizer/AuthorizationAttributeBuilder pair supports. // If the Authorizer does not recognize how to handle the AttributeRestrictions, the Authorizer should report an error. + // +kubebuilder:validation:PreserveUnknownFields optional k8s.io.apimachinery.pkg.runtime.RawExtension attributeRestrictions = 2; // APIGroups is the name of the APIGroup that contains the resources. If this field is empty, then both kubernetes and origin API groups are assumed. @@ -261,7 +259,6 @@ message ResourceAccessReviewResponse { // Role is a logical grouping of PolicyRules that can be referenced as a unit by RoleBindings. message Role { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Rules holds all the PolicyRules for this Role @@ -272,7 +269,6 @@ message Role { // It adds who information via (Users and Groups) OR Subjects and namespace information by which namespace it exists in. // RoleBindings in a given namespace only have effect in that namespace (excepting the master namespace which has power in all namespaces). message RoleBinding { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // UserNames holds all the usernames directly bound to the role. @@ -302,7 +298,6 @@ message RoleBinding { // RoleBindingList is a collection of RoleBindings message RoleBindingList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of RoleBindings @@ -315,7 +310,6 @@ message RoleBindingList { // belongs. If any one of those RoleBindingRestriction objects matches // a subject, rolebindings on that subject in the namespace are allowed. message RoleBindingRestriction { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Spec defines the matcher. @@ -324,7 +318,6 @@ message RoleBindingRestriction { // RoleBindingRestrictionList is a collection of RoleBindingRestriction objects. message RoleBindingRestrictionList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of RoleBindingRestriction objects. @@ -349,7 +342,6 @@ message RoleBindingRestrictionSpec { // RoleList is a collection of Roles message RoleList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of Roles diff --git a/vendor/github.com/openshift/api/authorization/v1/types.go b/vendor/github.com/openshift/api/authorization/v1/types.go index fde3ecf3d7..99623b7363 100644 --- a/vendor/github.com/openshift/api/authorization/v1/types.go +++ b/vendor/github.com/openshift/api/authorization/v1/types.go @@ -32,6 +32,7 @@ type PolicyRule struct { Verbs []string `json:"verbs" protobuf:"bytes,1,rep,name=verbs"` // AttributeRestrictions will vary depending on what the Authorizer/AuthorizationAttributeBuilder pair supports. // If the Authorizer does not recognize how to handle the AttributeRestrictions, the Authorizer should report an error. + // +kubebuilder:validation:PreserveUnknownFields AttributeRestrictions kruntime.RawExtension `json:"attributeRestrictions,omitempty" protobuf:"bytes,2,opt,name=attributeRestrictions"` // APIGroups is the name of the APIGroup that contains the resources. If this field is empty, then both kubernetes and origin API groups are assumed. // That means that if an action is requested against one of the enumerated resources in either the kubernetes or the origin API group, the request @@ -58,8 +59,7 @@ type IsPersonalSubjectAccessReview struct { // Role is a logical grouping of PolicyRules that can be referenced as a unit by RoleBindings. type Role struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Rules holds all the PolicyRules for this Role @@ -82,8 +82,7 @@ func (t OptionalNames) String() string { // It adds who information via (Users and Groups) OR Subjects and namespace information by which namespace it exists in. // RoleBindings in a given namespace only have effect in that namespace (excepting the master namespace which has power in all namespaces). type RoleBinding struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // UserNames holds all the usernames directly bound to the role. @@ -326,6 +325,7 @@ type Action struct { // IsNonResourceURL is true if this is a request for a non-resource URL (outside of the resource hieraarchy) IsNonResourceURL bool `json:"isNonResourceURL" protobuf:"varint,9,opt,name=isNonResourceURL"` // Content is the actual content of the request for create and update + // +kubebuilder:validation:PreserveUnknownFields Content kruntime.RawExtension `json:"content,omitempty" protobuf:"bytes,7,opt,name=content"` } @@ -334,7 +334,6 @@ type Action struct { // RoleBindingList is a collection of RoleBindings type RoleBindingList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of RoleBindings @@ -346,7 +345,6 @@ type RoleBindingList struct { // RoleList is a collection of Roles type RoleList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of Roles @@ -359,8 +357,7 @@ type RoleList struct { // ClusterRole is a logical grouping of PolicyRules that can be referenced as a unit by ClusterRoleBindings. type ClusterRole struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Rules holds all the PolicyRules for this ClusterRole @@ -380,8 +377,7 @@ type ClusterRole struct { // It adds who information via (Users and Groups) OR Subjects and namespace information by which namespace it exists in. // ClusterRoleBindings in a given namespace only have effect in that namespace (excepting the master namespace which has power in all namespaces). type ClusterRoleBinding struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // UserNames holds all the usernames directly bound to the role. @@ -428,7 +424,6 @@ type NamedClusterRoleBinding struct { // ClusterRoleBindingList is a collection of ClusterRoleBindings type ClusterRoleBindingList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of ClusterRoleBindings @@ -440,7 +435,6 @@ type ClusterRoleBindingList struct { // ClusterRoleList is a collection of ClusterRoles type ClusterRoleList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of ClusterRoles @@ -456,9 +450,7 @@ type ClusterRoleList struct { // belongs. If any one of those RoleBindingRestriction objects matches // a subject, rolebindings on that subject in the namespace are allowed. type RoleBindingRestriction struct { - metav1.TypeMeta `json:",inline"` - - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"` // Spec defines the matcher. @@ -486,8 +478,6 @@ type RoleBindingRestrictionSpec struct { // RoleBindingRestrictionList is a collection of RoleBindingRestriction objects. type RoleBindingRestrictionList struct { metav1.TypeMeta `json:",inline"` - - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of RoleBindingRestriction objects. diff --git a/vendor/github.com/openshift/api/authorization/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/authorization/v1/zz_generated.swagger_doc_generated.go index 15da0e310f..04b3c7f446 100644 --- a/vendor/github.com/openshift/api/authorization/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/authorization/v1/zz_generated.swagger_doc_generated.go @@ -30,7 +30,6 @@ func (Action) SwaggerDoc() map[string]string { var map_ClusterRole = map[string]string{ "": "ClusterRole is a logical grouping of PolicyRules that can be referenced as a unit by ClusterRoleBindings.", - "metadata": "Standard object's metadata.", "rules": "Rules holds all the PolicyRules for this ClusterRole", "aggregationRule": "AggregationRule is an optional field that describes how to build the Rules for this ClusterRole. If AggregationRule is set, then the Rules are controller managed and direct changes to Rules will be stomped by the controller.", } @@ -41,7 +40,6 @@ func (ClusterRole) SwaggerDoc() map[string]string { var map_ClusterRoleBinding = map[string]string{ "": "ClusterRoleBinding references a ClusterRole, but not contain it. It can reference any ClusterRole in the same namespace or in the global namespace. It adds who information via (Users and Groups) OR Subjects and namespace information by which namespace it exists in. ClusterRoleBindings in a given namespace only have effect in that namespace (excepting the master namespace which has power in all namespaces).", - "metadata": "Standard object's metadata.", "userNames": "UserNames holds all the usernames directly bound to the role. This field should only be specified when supporting legacy clients and servers. See Subjects for further details.", "groupNames": "GroupNames holds all the groups directly bound to the role. This field should only be specified when supporting legacy clients and servers. See Subjects for further details.", "subjects": "Subjects hold object references to authorize with this rule. This field is ignored if UserNames or GroupNames are specified to support legacy clients and servers. Thus newer clients that do not need to support backwards compatibility should send only fully qualified Subjects and should omit the UserNames and GroupNames fields. Clients that need to support backwards compatibility can use this field to build the UserNames and GroupNames.", @@ -53,9 +51,8 @@ func (ClusterRoleBinding) SwaggerDoc() map[string]string { } var map_ClusterRoleBindingList = map[string]string{ - "": "ClusterRoleBindingList is a collection of ClusterRoleBindings", - "metadata": "Standard object's metadata.", - "items": "Items is a list of ClusterRoleBindings", + "": "ClusterRoleBindingList is a collection of ClusterRoleBindings", + "items": "Items is a list of ClusterRoleBindings", } func (ClusterRoleBindingList) SwaggerDoc() map[string]string { @@ -63,9 +60,8 @@ func (ClusterRoleBindingList) SwaggerDoc() map[string]string { } var map_ClusterRoleList = map[string]string{ - "": "ClusterRoleList is a collection of ClusterRoles", - "metadata": "Standard object's metadata.", - "items": "Items is a list of ClusterRoles", + "": "ClusterRoleList is a collection of ClusterRoles", + "items": "Items is a list of ClusterRoles", } func (ClusterRoleList) SwaggerDoc() map[string]string { @@ -184,9 +180,8 @@ func (ResourceAccessReviewResponse) SwaggerDoc() map[string]string { } var map_Role = map[string]string{ - "": "Role is a logical grouping of PolicyRules that can be referenced as a unit by RoleBindings.", - "metadata": "Standard object's metadata.", - "rules": "Rules holds all the PolicyRules for this Role", + "": "Role is a logical grouping of PolicyRules that can be referenced as a unit by RoleBindings.", + "rules": "Rules holds all the PolicyRules for this Role", } func (Role) SwaggerDoc() map[string]string { @@ -195,7 +190,6 @@ func (Role) SwaggerDoc() map[string]string { var map_RoleBinding = map[string]string{ "": "RoleBinding references a Role, but not contain it. It can reference any Role in the same namespace or in the global namespace. It adds who information via (Users and Groups) OR Subjects and namespace information by which namespace it exists in. RoleBindings in a given namespace only have effect in that namespace (excepting the master namespace which has power in all namespaces).", - "metadata": "Standard object's metadata.", "userNames": "UserNames holds all the usernames directly bound to the role. This field should only be specified when supporting legacy clients and servers. See Subjects for further details.", "groupNames": "GroupNames holds all the groups directly bound to the role. This field should only be specified when supporting legacy clients and servers. See Subjects for further details.", "subjects": "Subjects hold object references to authorize with this rule. This field is ignored if UserNames or GroupNames are specified to support legacy clients and servers. Thus newer clients that do not need to support backwards compatibility should send only fully qualified Subjects and should omit the UserNames and GroupNames fields. Clients that need to support backwards compatibility can use this field to build the UserNames and GroupNames.", @@ -207,9 +201,8 @@ func (RoleBinding) SwaggerDoc() map[string]string { } var map_RoleBindingList = map[string]string{ - "": "RoleBindingList is a collection of RoleBindings", - "metadata": "Standard object's metadata.", - "items": "Items is a list of RoleBindings", + "": "RoleBindingList is a collection of RoleBindings", + "items": "Items is a list of RoleBindings", } func (RoleBindingList) SwaggerDoc() map[string]string { @@ -217,9 +210,8 @@ func (RoleBindingList) SwaggerDoc() map[string]string { } var map_RoleBindingRestriction = map[string]string{ - "": "RoleBindingRestriction is an object that can be matched against a subject (user, group, or service account) to determine whether rolebindings on that subject are allowed in the namespace to which the RoleBindingRestriction belongs. If any one of those RoleBindingRestriction objects matches a subject, rolebindings on that subject in the namespace are allowed.", - "metadata": "Standard object's metadata.", - "spec": "Spec defines the matcher.", + "": "RoleBindingRestriction is an object that can be matched against a subject (user, group, or service account) to determine whether rolebindings on that subject are allowed in the namespace to which the RoleBindingRestriction belongs. If any one of those RoleBindingRestriction objects matches a subject, rolebindings on that subject in the namespace are allowed.", + "spec": "Spec defines the matcher.", } func (RoleBindingRestriction) SwaggerDoc() map[string]string { @@ -227,9 +219,8 @@ func (RoleBindingRestriction) SwaggerDoc() map[string]string { } var map_RoleBindingRestrictionList = map[string]string{ - "": "RoleBindingRestrictionList is a collection of RoleBindingRestriction objects.", - "metadata": "Standard object's metadata.", - "items": "Items is a list of RoleBindingRestriction objects.", + "": "RoleBindingRestrictionList is a collection of RoleBindingRestriction objects.", + "items": "Items is a list of RoleBindingRestriction objects.", } func (RoleBindingRestrictionList) SwaggerDoc() map[string]string { @@ -248,9 +239,8 @@ func (RoleBindingRestrictionSpec) SwaggerDoc() map[string]string { } var map_RoleList = map[string]string{ - "": "RoleList is a collection of Roles", - "metadata": "Standard object's metadata.", - "items": "Items is a list of Roles", + "": "RoleList is a collection of Roles", + "items": "Items is a list of Roles", } func (RoleList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/build/v1/generated.proto b/vendor/github.com/openshift/api/build/v1/generated.proto index cb374e22e4..2aa49f421e 100644 --- a/vendor/github.com/openshift/api/build/v1/generated.proto +++ b/vendor/github.com/openshift/api/build/v1/generated.proto @@ -14,7 +14,6 @@ option go_package = "v1"; // BinaryBuildRequestOptions are the options required to fully speficy a binary build request message BinaryBuildRequestOptions { - // metadata for BinaryBuildRequestOptions. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // asFile determines if the binary should be created as a file within the source rather than extracted as an archive @@ -60,7 +59,6 @@ message BitbucketWebHookCause { // Build encapsulates the inputs needed to produce a new deployable image, as well as // the status of the execution and a reference to the Pod which executed the build. message Build { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // spec is all the inputs used to execute the build. @@ -74,7 +72,6 @@ message Build { // // Each build created by a build configuration is numbered and refers back to its parent configuration. Multiple builds can be triggered at once. Builds that do not have "output" set can be used to test code or run a verification build. message BuildConfig { - // metadata for BuildConfig. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // spec holds all the input necessary to produce a new build, and the conditions when @@ -87,7 +84,6 @@ message BuildConfig { // BuildConfigList is a collection of BuildConfigs. message BuildConfigList { - // metadata for BuildConfigList. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // items is a list of build configs @@ -128,7 +124,6 @@ message BuildConfigStatus { // BuildList is a collection of Builds. message BuildList { - // metadata for BuildList. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // items is a list of builds @@ -297,7 +292,6 @@ message BuildPostCommitSpec { // BuildRequest is the resource used to pass parameters to build generator message BuildRequest { - // metadata for BuildRequest. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // revision is the information from the source for a specific repo snapshot. diff --git a/vendor/github.com/openshift/api/build/v1/types.go b/vendor/github.com/openshift/api/build/v1/types.go index 82bb7883ad..13a0f8cea3 100644 --- a/vendor/github.com/openshift/api/build/v1/types.go +++ b/vendor/github.com/openshift/api/build/v1/types.go @@ -16,8 +16,7 @@ import ( // Build encapsulates the inputs needed to produce a new deployable image, as well as // the status of the execution and a reference to the Pod which executed the build. type Build struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // spec is all the inputs used to execute the build. @@ -874,8 +873,7 @@ type ImageLabel struct { // // Each build created by a build configuration is numbered and refers back to its parent configuration. Multiple builds can be triggered at once. Builds that do not have "output" set can be used to test code or run a verification build. type BuildConfig struct { - metav1.TypeMeta `json:",inline"` - // metadata for BuildConfig. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // spec holds all the input necessary to produce a new build, and the conditions when @@ -1035,7 +1033,6 @@ const ( // BuildList is a collection of Builds. type BuildList struct { metav1.TypeMeta `json:",inline"` - // metadata for BuildList. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // items is a list of builds @@ -1047,7 +1044,6 @@ type BuildList struct { // BuildConfigList is a collection of BuildConfigs. type BuildConfigList struct { metav1.TypeMeta `json:",inline"` - // metadata for BuildConfigList. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // items is a list of build configs @@ -1115,8 +1111,7 @@ type SourceStrategyOptions struct { // BuildRequest is the resource used to pass parameters to build generator type BuildRequest struct { - metav1.TypeMeta `json:",inline"` - // metadata for BuildRequest. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // revision is the information from the source for a specific repo snapshot. @@ -1154,8 +1149,7 @@ type BuildRequest struct { // BinaryBuildRequestOptions are the options required to fully speficy a binary build request type BinaryBuildRequestOptions struct { - metav1.TypeMeta `json:",inline"` - // metadata for BinaryBuildRequestOptions. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // asFile determines if the binary should be created as a file within the source rather than extracted as an archive diff --git a/vendor/github.com/openshift/api/build/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/build/v1/zz_generated.swagger_doc_generated.go index 1436e65543..affa774e17 100644 --- a/vendor/github.com/openshift/api/build/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/build/v1/zz_generated.swagger_doc_generated.go @@ -13,7 +13,6 @@ package v1 // AUTO-GENERATED FUNCTIONS START HERE var map_BinaryBuildRequestOptions = map[string]string{ "": "BinaryBuildRequestOptions are the options required to fully speficy a binary build request", - "metadata": "metadata for BinaryBuildRequestOptions.", "asFile": "asFile determines if the binary should be created as a file within the source rather than extracted as an archive", "revision.commit": "revision.commit is the value identifying a specific commit", "revision.message": "revision.message is the description of a specific commit", @@ -45,10 +44,9 @@ func (BitbucketWebHookCause) SwaggerDoc() map[string]string { } var map_Build = map[string]string{ - "": "Build encapsulates the inputs needed to produce a new deployable image, as well as the status of the execution and a reference to the Pod which executed the build.", - "metadata": "Standard object's metadata.", - "spec": "spec is all the inputs used to execute the build.", - "status": "status is the current status of the build.", + "": "Build encapsulates the inputs needed to produce a new deployable image, as well as the status of the execution and a reference to the Pod which executed the build.", + "spec": "spec is all the inputs used to execute the build.", + "status": "status is the current status of the build.", } func (Build) SwaggerDoc() map[string]string { @@ -56,10 +54,9 @@ func (Build) SwaggerDoc() map[string]string { } var map_BuildConfig = map[string]string{ - "": "Build configurations define a build process for new container images. There are three types of builds possible - a container image build using a Dockerfile, a Source-to-Image build that uses a specially prepared base image that accepts source code that it can make runnable, and a custom build that can run // arbitrary container images as a base and accept the build parameters. Builds run on the cluster and on completion are pushed to the container image registry specified in the \"output\" section. A build can be triggered via a webhook, when the base image changes, or when a user manually requests a new build be // created.\n\nEach build created by a build configuration is numbered and refers back to its parent configuration. Multiple builds can be triggered at once. Builds that do not have \"output\" set can be used to test code or run a verification build.", - "metadata": "metadata for BuildConfig.", - "spec": "spec holds all the input necessary to produce a new build, and the conditions when to trigger them.", - "status": "status holds any relevant information about a build config", + "": "Build configurations define a build process for new container images. There are three types of builds possible - a container image build using a Dockerfile, a Source-to-Image build that uses a specially prepared base image that accepts source code that it can make runnable, and a custom build that can run // arbitrary container images as a base and accept the build parameters. Builds run on the cluster and on completion are pushed to the container image registry specified in the \"output\" section. A build can be triggered via a webhook, when the base image changes, or when a user manually requests a new build be // created.\n\nEach build created by a build configuration is numbered and refers back to its parent configuration. Multiple builds can be triggered at once. Builds that do not have \"output\" set can be used to test code or run a verification build.", + "spec": "spec holds all the input necessary to produce a new build, and the conditions when to trigger them.", + "status": "status holds any relevant information about a build config", } func (BuildConfig) SwaggerDoc() map[string]string { @@ -67,9 +64,8 @@ func (BuildConfig) SwaggerDoc() map[string]string { } var map_BuildConfigList = map[string]string{ - "": "BuildConfigList is a collection of BuildConfigs.", - "metadata": "metadata for BuildConfigList.", - "items": "items is a list of build configs", + "": "BuildConfigList is a collection of BuildConfigs.", + "items": "items is a list of build configs", } func (BuildConfigList) SwaggerDoc() map[string]string { @@ -98,9 +94,8 @@ func (BuildConfigStatus) SwaggerDoc() map[string]string { } var map_BuildList = map[string]string{ - "": "BuildList is a collection of Builds.", - "metadata": "metadata for BuildList.", - "items": "items is a list of builds", + "": "BuildList is a collection of Builds.", + "items": "items is a list of builds", } func (BuildList) SwaggerDoc() map[string]string { @@ -157,7 +152,6 @@ func (BuildPostCommitSpec) SwaggerDoc() map[string]string { var map_BuildRequest = map[string]string{ "": "BuildRequest is the resource used to pass parameters to build generator", - "metadata": "metadata for BuildRequest.", "revision": "revision is the information from the source for a specific repo snapshot.", "triggeredByImage": "triggeredByImage is the Image that triggered this build.", "from": "from is the reference to the ImageStreamTag that triggered the build.", diff --git a/vendor/github.com/openshift/api/config/v1/0000_03_config-operator_01_operatorhub.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_03_config-operator_01_operatorhub.crd.yaml new file mode 100644 index 0000000000..e2d2bcf286 --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_03_config-operator_01_operatorhub.crd.yaml @@ -0,0 +1,101 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: operatorhubs.config.openshift.io +spec: + group: config.openshift.io + names: + kind: OperatorHub + listKind: OperatorHubList + plural: operatorhubs + singular: operatorhub + scope: Cluster + preserveUnknownField: false + subresources: + status: {} + version: v1 + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: OperatorHub is the Schema for the operatorhubs API. It can be used + to change the state of the default hub sources for OperatorHub on the cluster + from enabled to disabled and vice versa. + type: object + 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: + description: OperatorHubSpec defines the desired state of OperatorHub + type: object + properties: + disableAllDefaultSources: + description: disableAllDefaultSources allows you to disable all the + default hub sources. If this is true, a specific entry in sources + can be used to enable a default source. If this is false, a specific + entry in sources can be used to disable or enable a default source. + type: boolean + sources: + description: sources is the list of default hub sources and their configuration. + If the list is empty, it implies that the default hub sources are + enabled on the cluster unless disableAllDefaultSources is true. If + disableAllDefaultSources is true and sources is not empty, the configuration + present in sources will take precedence. The list of default hub sources + and their current state will always be reflected in the status block. + type: array + items: + description: HubSource is used to specify the hub source and its configuration + type: object + properties: + disabled: + description: disabled is used to disable a default hub source + on cluster + type: boolean + name: + description: name is the name of one of the default hub sources + type: string + maxLength: 253 + minLength: 1 + status: + description: OperatorHubStatus defines the observed state of OperatorHub. + The current state of the default hub sources will always be reflected + here. + type: object + properties: + sources: + description: sources encapsulates the result of applying the configuration + for each hub source + type: array + items: + description: HubSourceStatus is used to reflect the current state + of applying the configuration to a default source + type: object + properties: + disabled: + description: disabled is used to disable a default hub source + on cluster + type: boolean + message: + description: message provides more information regarding failures + type: string + name: + description: name is the name of one of the default hub sources + type: string + maxLength: 253 + minLength: 1 + status: + description: status indicates success or failure in applying the + configuration + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_03_config-operator_01_proxy.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_03_config-operator_01_proxy.crd.yaml new file mode 100644 index 0000000000..a65f38418e --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_03_config-operator_01_proxy.crd.yaml @@ -0,0 +1,98 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: proxies.config.openshift.io +spec: + group: config.openshift.io + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + names: + kind: Proxy + listKind: ProxyList + plural: proxies + singular: proxy + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: Proxy holds cluster-wide information on how to configure default + proxies for the cluster. The canonical name is `cluster` + type: object + required: + - spec + 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: + description: Spec holds user-settable values for the proxy configuration + type: object + properties: + httpProxy: + description: httpProxy is the URL of the proxy for HTTP requests. Empty + means unset and will not result in an env var. + type: string + httpsProxy: + description: httpsProxy is the URL of the proxy for HTTPS requests. Empty + means unset and will not result in an env var. + type: string + noProxy: + description: noProxy is a comma-separated list of hostnames and/or CIDRs + for which the proxy should not be used. Empty means unset and will + not result in an env var. + type: string + readinessEndpoints: + description: readinessEndpoints is a list of endpoints used to verify + readiness of the proxy. + type: array + items: + type: string + trustedCA: + description: "trustedCA is a reference to a ConfigMap containing a CA + certificate bundle used for client egress HTTPS connections. The certificate + bundle must be from the CA that signed the proxy's certificate and + be signed for everything. The trustedCA field should only be consumed + by a proxy validator. The validator is responsible for reading the + certificate bundle from required key \"ca-bundle.crt\" and copying + it to a ConfigMap named \"trusted-ca-bundle\" in the \"openshift-config-managed\" + namespace. The namespace for the ConfigMap referenced by trustedCA + is \"openshift-config\". Here is an example ConfigMap (in yaml): \n + apiVersion: v1 kind: ConfigMap metadata: name: user-ca-bundle namespace: + openshift-config data: ca-bundle.crt: | -----BEGIN CERTIFICATE----- + \ Custom CA certificate bundle. -----END CERTIFICATE-----" + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced config + map + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object + properties: + httpProxy: + description: httpProxy is the URL of the proxy for HTTP requests. + type: string + httpsProxy: + description: httpsProxy is the URL of the proxy for HTTPS requests. + type: string + noProxy: + description: noProxy is a comma-separated list of hostnames and/or CIDRs + for which the proxy should not be used. + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_apiserver.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_apiserver.crd.yaml new file mode 100644 index 0000000000..58c0067f09 --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_apiserver.crd.yaml @@ -0,0 +1,209 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: apiservers.config.openshift.io +spec: + group: config.openshift.io + scope: Cluster + preserveUnknownField: false + names: + kind: APIServer + singular: apiserver + plural: apiservers + listKind: APIServerList + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: APIServer holds configuration (like serving certificates, client + CA and CORS domains) shared by all API servers in the system, among them especially + kube-apiserver and openshift-apiserver. The canonical name of an instance + is 'cluster'. + type: object + required: + - spec + 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: + type: object + properties: + additionalCORSAllowedOrigins: + description: additionalCORSAllowedOrigins lists additional, user-defined + regular expressions describing hosts for which the API server allows + access using the CORS headers. This may be needed to access the API + and the integrated OAuth server from JavaScript applications. The + values are regular expressions that correspond to the Golang regular + expression language. + type: array + items: + type: string + clientCA: + description: 'clientCA references a ConfigMap containing a certificate + bundle for the signers that will be recognized for incoming client + certificates in addition to the operator managed signers. If this + is empty, then only operator managed signers are valid. You usually + only have to set this if you have your own PKI you wish to honor client + certificates from. The ConfigMap must exist in the openshift-config + namespace and contain the following required fields: - ConfigMap.Data["ca-bundle.crt"] + - CA bundle.' + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced config + map + type: string + encryption: + description: encryption allows the configuration of encryption of resources + at the datastore layer. + type: object + properties: + type: + description: "type defines what encryption type should be used to + encrypt resources at the datastore layer. When this field is unset + (i.e. when it is set to the empty string), identity is implied. + The behavior of unset can and will change over time. Even if + encryption is enabled by default, the meaning of unset may change + to a different encryption type based on changes in best practices. + \n When encryption is enabled, all sensitive resources shipped + with the platform are encrypted. This list of sensitive resources + can and will change over time. The current authoritative list + is: \n 1. secrets 2. configmaps 3. routes.route.openshift.io + \ 4. oauthaccesstokens.oauth.openshift.io 5. oauthauthorizetokens.oauth.openshift.io" + type: string + enum: + - "" + - identity + - aescbc + servingCerts: + description: servingCert is the TLS cert info for serving secure traffic. + If not specified, operator managed certificates will be used for serving + secure traffic. + type: object + properties: + namedCertificates: + description: namedCertificates references secrets containing the + TLS cert info for serving secure traffic to specific hostnames. + If no named certificates are provided, or no named certificates + match the server name as understood by a client, the defaultServingCertificate + will be used. + type: array + items: + description: APIServerNamedServingCert maps a server DNS name, + as understood by a client, to a certificate. + type: object + properties: + names: + description: names is a optional list of explicit DNS names + (leading wildcards allowed) that should use this certificate + to serve secure traffic. If no names are provided, the implicit + names will be extracted from the certificates. Exact names + trump over wildcard names. Explicit names defined here trump + over extracted implicit names. + type: array + items: + type: string + servingCertificate: + description: 'servingCertificate references a kubernetes.io/tls + type secret containing the TLS cert info for serving secure + traffic. The secret must exist in the openshift-config namespace + and contain the following required fields: - Secret.Data["tls.key"] + - TLS private key. - Secret.Data["tls.crt"] - TLS certificate.' + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + tlsSecurityProfile: + description: "tlsSecurityProfile specifies settings for TLS connections + for externally exposed servers. \n If unset, a default (which may + change between releases) is chosen." + type: object + properties: + custom: + description: "custom is a user-defined TLS security profile. Be + extremely careful using a custom profile as invalid configurations + can be catastrophic. An example custom profile looks like this: + \n ciphers: - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + \ - ECDHE-RSA-AES128-GCM-SHA256 - ECDHE-ECDSA-AES128-GCM-SHA256 + \ minTLSVersion: TLSv1.1" + type: object + properties: + ciphers: + description: "ciphers is used to specify the cipher algorithms + that are negotiated during the TLS handshake. Operators may + remove entries their operands do not support. For example, + to use DES-CBC3-SHA (yaml): \n ciphers: - DES-CBC3-SHA" + type: array + items: + type: string + minTLSVersion: + description: "minTLSVersion is used to specify the minimal version + of the TLS protocol that is negotiated during the TLS handshake. + For example, to use TLS versions 1.1, 1.2 and 1.3 (yaml): + \n minTLSVersion: TLSv1.1" + type: string + nullable: true + intermediate: + description: "intermediate is a TLS security profile based on: \n + https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + \ - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + \ - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 + \ - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + \ - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + \ minTLSVersion: TLSv1.2" + type: object + nullable: true + modern: + description: "modern is a TLS security profile based on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + \ - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + \ minTLSVersion: TLSv1.3" + type: object + nullable: true + old: + description: "old is a TLS security profile based on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility + \n and looks like this (yaml): \n ciphers: - TLS_AES_128_GCM_SHA256 + \ - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 + \ - ECDHE-ECDSA-AES128-GCM-SHA256 - ECDHE-RSA-AES128-GCM-SHA256 + \ - ECDHE-ECDSA-AES256-GCM-SHA384 - ECDHE-RSA-AES256-GCM-SHA384 + \ - ECDHE-ECDSA-CHACHA20-POLY1305 - ECDHE-RSA-CHACHA20-POLY1305 + \ - ECDHE-ECDSA-AES128-SHA256 - ECDHE-RSA-AES128-SHA256 + \ - ECDHE-ECDSA-AES128-SHA - ECDHE-RSA-AES128-SHA - + ECDHE-ECDSA-AES256-SHA - ECDHE-RSA-AES256-SHA - AES128-GCM-SHA256 + \ - AES256-GCM-SHA384 - AES128-SHA256 - AES128-SHA + \ - AES256-SHA - DES-CBC3-SHA minTLSVersion: TLSv1.0" + type: object + nullable: true + type: + description: "type is one of Old, Intermediate, Modern or Custom. + Custom provides the ability to specify individual TLS security + profile parameters. Old, Intermediate and Modern are TLS security + profiles based on: \n https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations + \n The profiles are intent based, so they may change over time + as new ciphers are developed and existing ciphers are found to + be insecure. Depending on precisely which ciphers are available + to a process, the list may be reduced." + type: string + status: + type: object diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd.yaml new file mode 100644 index 0000000000..501c8f064d --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_authentication.crd.yaml @@ -0,0 +1,123 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: authentications.config.openshift.io +spec: + group: config.openshift.io + names: + kind: Authentication + listKind: AuthenticationList + plural: authentications + singular: authentication + scope: Cluster + preserveUnknownField: false + subresources: + status: {} + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: Authentication specifies cluster-wide settings for authentication + (like OAuth and webhook token authenticators). The canonical name of an instance + is `cluster`. + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + oauthMetadata: + description: 'oauthMetadata contains the discovery endpoint data for + OAuth 2.0 Authorization Server Metadata for an external OAuth server. + This discovery document can be viewed from its served location: oc + get --raw ''/.well-known/oauth-authorization-server'' For further + details, see the IETF Draft: https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2 + If oauthMetadata.name is non-empty, this value has precedence over + any metadata reference stored in status. The key "oauthMetadata" is + used to locate the data. If specified and the config map or expected + key is not found, no metadata is served. If the specified metadata + is not valid, no metadata is served. The namespace for this config + map is openshift-config.' + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced config + map + type: string + type: + description: type identifies the cluster managed, user facing authentication + mode in use. Specifically, it manages the component that responds + to login attempts. The default is IntegratedOAuth. + type: string + webhookTokenAuthenticators: + description: webhookTokenAuthenticators configures remote token reviewers. + These remote authentication webhooks can be used to verify bearer + tokens via the tokenreviews.authentication.k8s.io REST API. This + is required to honor bearer tokens that are provisioned by an external + authentication service. The namespace for these secrets is openshift-config. + type: array + items: + description: webhookTokenAuthenticator holds the necessary configuration + options for a remote token authenticator + type: object + properties: + kubeConfig: + description: 'kubeConfig contains kube config file data which + describes how to access the remote webhook service. For further + details, see: https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication + The key "kubeConfig" is used to locate the data. If the secret + or expected key is not found, the webhook is not honored. If + the specified kube config data is not valid, the webhook is + not honored. The namespace for this secret is determined by + the point of use.' + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced secret + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object + properties: + integratedOAuthMetadata: + description: 'integratedOAuthMetadata contains the discovery endpoint + data for OAuth 2.0 Authorization Server Metadata for the in-cluster + integrated OAuth server. This discovery document can be viewed from + its served location: oc get --raw ''/.well-known/oauth-authorization-server'' + For further details, see the IETF Draft: https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2 + This contains the observed value based on cluster state. An explicitly + set value in spec.oauthMetadata has precedence over this field. This + field has no meaning if authentication spec.type is not set to IntegratedOAuth. + The key "oauthMetadata" is used to locate the data. If the config + map or expected key is not found, no metadata is served. If the specified + metadata is not valid, no metadata is served. The namespace for this + config map is openshift-config-managed.' + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced config + map + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_build.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_build.crd.yaml new file mode 100644 index 0000000000..984b30b72b --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_build.crd.yaml @@ -0,0 +1,366 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: builds.config.openshift.io +spec: + group: config.openshift.io + scope: Cluster + preserveUnknownField: false + names: + kind: Build + singular: build + plural: builds + listKind: BuildList + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: "Build configures the behavior of OpenShift builds for the entire + cluster. This includes default settings that can be overridden in BuildConfig + objects, and overrides which are applied to all builds. \n The canonical name + is \"cluster\"" + type: object + required: + - spec + 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: + description: Spec holds user-settable values for the build controller configuration + type: object + properties: + additionalTrustedCA: + description: "AdditionalTrustedCA is a reference to a ConfigMap containing + additional CAs that should be trusted for image pushes and pulls during + builds. The namespace for this config map is openshift-config. \n + DEPRECATED: Additional CAs for image pull and push should be set on + image.config.openshift.io/cluster instead." + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced config + map + type: string + buildDefaults: + description: BuildDefaults controls the default information for Builds + type: object + properties: + defaultProxy: + description: "DefaultProxy contains the default proxy settings for + all build operations, including image pull/push and source download. + \n Values can be overrode by setting the `HTTP_PROXY`, `HTTPS_PROXY`, + and `NO_PROXY` environment variables in the build config's strategy." + type: object + properties: + httpProxy: + description: httpProxy is the URL of the proxy for HTTP requests. Empty + means unset and will not result in an env var. + type: string + httpsProxy: + description: httpsProxy is the URL of the proxy for HTTPS requests. Empty + means unset and will not result in an env var. + type: string + noProxy: + description: noProxy is a comma-separated list of hostnames + and/or CIDRs for which the proxy should not be used. Empty + means unset and will not result in an env var. + type: string + readinessEndpoints: + description: readinessEndpoints is a list of endpoints used + to verify readiness of the proxy. + type: array + items: + type: string + trustedCA: + description: "trustedCA is a reference to a ConfigMap containing + a CA certificate bundle used for client egress HTTPS connections. + The certificate bundle must be from the CA that signed the + proxy's certificate and be signed for everything. The trustedCA + field should only be consumed by a proxy validator. The validator + is responsible for reading the certificate bundle from required + key \"ca-bundle.crt\" and copying it to a ConfigMap named + \"trusted-ca-bundle\" in the \"openshift-config-managed\" + namespace. The namespace for the ConfigMap referenced by trustedCA + is \"openshift-config\". Here is an example ConfigMap (in + yaml): \n apiVersion: v1 kind: ConfigMap metadata: name: + user-ca-bundle namespace: openshift-config data: ca-bundle.crt: + | -----BEGIN CERTIFICATE----- Custom CA certificate + bundle. -----END CERTIFICATE-----" + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + env: + description: Env is a set of default environment variables that + will be applied to the build if the specified variables do not + exist on the build + type: array + items: + description: EnvVar represents an environment variable present + in a Container. + type: object + required: + - name + properties: + name: + description: Name of the environment variable. Must be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are expanded + using the previous defined environment variables in the + container and any service environment variables. If a variable + cannot be resolved, the reference in the input string will + be unchanged. The $(VAR_NAME) syntax can be escaped with + a double $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable exists or + not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's value. + Cannot be used if value is not empty. + type: object + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + type: object + required: + - key + 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 + fieldRef: + description: 'Selects a field of the pod: supports metadata.name, + metadata.namespace, metadata.labels, metadata.annotations, + spec.nodeName, spec.serviceAccountName, status.hostIP, + status.podIP.' + type: object + required: + - fieldPath + properties: + apiVersion: + description: Version of the schema the FieldPath is + written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in the specified + API version. + type: string + resourceFieldRef: + description: 'Selects a resource of the container: only + resources limits and requests (limits.cpu, limits.memory, + limits.ephemeral-storage, requests.cpu, requests.memory + and requests.ephemeral-storage) are currently supported.' + type: object + required: + - resource + properties: + containerName: + description: 'Container name: required for volumes, + optional for env vars' + type: string + divisor: + description: Specifies the output format of the exposed + resources, defaults to "1" + type: string + resource: + description: 'Required: resource to select' + type: string + secretKeyRef: + description: Selects a key of a secret in the pod's namespace + type: object + required: + - key + 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 + gitProxy: + description: "GitProxy contains the proxy settings for git operations + only. If set, this will override any Proxy settings for all git + commands, such as git clone. \n Values that are not set here will + be inherited from DefaultProxy." + type: object + properties: + httpProxy: + description: httpProxy is the URL of the proxy for HTTP requests. Empty + means unset and will not result in an env var. + type: string + httpsProxy: + description: httpsProxy is the URL of the proxy for HTTPS requests. Empty + means unset and will not result in an env var. + type: string + noProxy: + description: noProxy is a comma-separated list of hostnames + and/or CIDRs for which the proxy should not be used. Empty + means unset and will not result in an env var. + type: string + readinessEndpoints: + description: readinessEndpoints is a list of endpoints used + to verify readiness of the proxy. + type: array + items: + type: string + trustedCA: + description: "trustedCA is a reference to a ConfigMap containing + a CA certificate bundle used for client egress HTTPS connections. + The certificate bundle must be from the CA that signed the + proxy's certificate and be signed for everything. The trustedCA + field should only be consumed by a proxy validator. The validator + is responsible for reading the certificate bundle from required + key \"ca-bundle.crt\" and copying it to a ConfigMap named + \"trusted-ca-bundle\" in the \"openshift-config-managed\" + namespace. The namespace for the ConfigMap referenced by trustedCA + is \"openshift-config\". Here is an example ConfigMap (in + yaml): \n apiVersion: v1 kind: ConfigMap metadata: name: + user-ca-bundle namespace: openshift-config data: ca-bundle.crt: + | -----BEGIN CERTIFICATE----- Custom CA certificate + bundle. -----END CERTIFICATE-----" + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + imageLabels: + description: ImageLabels is a list of docker labels that are applied + to the resulting image. User can override a default label by providing + a label with the same name in their Build/BuildConfig. + type: array + items: + type: object + properties: + name: + description: Name defines the name of the label. It must have + non-zero length. + type: string + value: + description: Value defines the literal value of the label. + type: string + resources: + description: Resources defines resource requirements to execute + the build. + type: object + properties: + limits: + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + additionalProperties: + type: string + requests: + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + additionalProperties: + type: string + buildOverrides: + description: BuildOverrides controls override settings for builds + type: object + properties: + imageLabels: + description: ImageLabels is a list of docker labels that are applied + to the resulting image. If user provided a label in their Build/BuildConfig + with the same name as one in this list, the user's label will + be overwritten. + type: array + items: + type: object + properties: + name: + description: Name defines the name of the label. It must have + non-zero length. + type: string + value: + description: Value defines the literal value of the label. + type: string + nodeSelector: + description: NodeSelector is a selector which must be true for the + build pod to fit on a node + type: object + additionalProperties: + type: string + tolerations: + description: Tolerations is a list of Tolerations that will override + any existing tolerations set on a build pod. + type: array + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using the + matching operator . + type: object + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to + Equal. Exists is equivalent to wildcard for value, so that + a pod can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do + not evict). Zero and negative values will be treated as + 0 (evict immediately) by the system. + type: integer + format: int64 + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_console.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_console.crd.yaml new file mode 100644 index 0000000000..33791bc223 --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_console.crd.yaml @@ -0,0 +1,70 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: consoles.config.openshift.io +spec: + scope: Cluster + preserveUnknownField: false + group: config.openshift.io + names: + kind: Console + listKind: ConsoleList + plural: consoles + singular: console + subresources: + status: {} + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: Console holds cluster-wide configuration for the web console, including + the logout URL, and reports the public URL of the console. The canonical name + is `cluster`. + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + authentication: + description: ConsoleAuthentication defines a list of optional configuration + for console authentication. + type: object + properties: + logoutRedirect: + description: 'An optional, absolute URL to redirect web browsers + to after logging out of the console. If not specified, it will + redirect to the default login page. This is required when using + an identity provider that supports single sign-on (SSO) such as: + - OpenID (Keycloak, Azure) - RequestHeader (GSSAPI, SSPI, SAML) + - OAuth (GitHub, GitLab, Google) Logging out of the console will + destroy the user''s token. The logoutRedirect provides the user + the option to perform single logout (SLO) through the identity + provider to destroy their single sign-on session.' + type: string + pattern: ^$|^((https):\/\/?)[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/?))$ + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object + properties: + consoleURL: + description: The URL for the console. This will be derived from the + host for the route that is created for the console. + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_dns.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_dns.crd.yaml new file mode 100644 index 0000000000..b500a2d61b --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_dns.crd.yaml @@ -0,0 +1,100 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: dnses.config.openshift.io +spec: + group: config.openshift.io + names: + kind: DNS + listKind: DNSList + plural: dnses + singular: dns + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: DNS holds cluster-wide information about DNS. The canonical name + is `cluster` + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + baseDomain: + description: "baseDomain is the base domain of the cluster. All managed + DNS records will be sub-domains of this base. \n For example, given + the base domain `openshift.example.com`, an API server DNS record + may be created for `cluster-api.openshift.example.com`. \n Once set, + this field cannot be changed." + type: string + privateZone: + description: "privateZone is the location where all the DNS records + that are only available internally to the cluster exist. \n If this + field is nil, no private records should be created. \n Once set, this + field cannot be changed." + type: object + properties: + id: + description: "id is the identifier that can be used to find the + DNS hosted zone. \n on AWS zone can be fetched using `ID` as id + in [1] on Azure zone can be fetched using `ID` as a pre-determined + name in [2], on GCP zone can be fetched using `ID` as a pre-determined + name in [3]. \n [1]: https://docs.aws.amazon.com/cli/latest/reference/route53/get-hosted-zone.html#options + [2]: https://docs.microsoft.com/en-us/cli/azure/network/dns/zone?view=azure-cli-latest#az-network-dns-zone-show + [3]: https://cloud.google.com/dns/docs/reference/v1/managedZones/get" + type: string + tags: + description: "tags can be used to query the DNS hosted zone. \n + on AWS, resourcegroupstaggingapi [1] can be used to fetch a zone + using `Tags` as tag-filters, \n [1]: https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/get-resources.html#options" + type: object + additionalProperties: + type: string + publicZone: + description: "publicZone is the location where all the DNS records that + are publicly accessible to the internet exist. \n If this field is + nil, no public records should be created. \n Once set, this field + cannot be changed." + type: object + properties: + id: + description: "id is the identifier that can be used to find the + DNS hosted zone. \n on AWS zone can be fetched using `ID` as id + in [1] on Azure zone can be fetched using `ID` as a pre-determined + name in [2], on GCP zone can be fetched using `ID` as a pre-determined + name in [3]. \n [1]: https://docs.aws.amazon.com/cli/latest/reference/route53/get-hosted-zone.html#options + [2]: https://docs.microsoft.com/en-us/cli/azure/network/dns/zone?view=azure-cli-latest#az-network-dns-zone-show + [3]: https://cloud.google.com/dns/docs/reference/v1/managedZones/get" + type: string + tags: + description: "tags can be used to query the DNS hosted zone. \n + on AWS, resourcegroupstaggingapi [1] can be used to fetch a zone + using `Tags` as tag-filters, \n [1]: https://docs.aws.amazon.com/cli/latest/reference/resourcegroupstaggingapi/get-resources.html#options" + type: object + additionalProperties: + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_featuregate.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_featuregate.crd.yaml new file mode 100644 index 0000000000..f2ccf3a4ea --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_featuregate.crd.yaml @@ -0,0 +1,76 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: featuregates.config.openshift.io +spec: + group: config.openshift.io + version: v1 + scope: Cluster + preserveUnknownField: false + names: + kind: FeatureGate + singular: featuregate + plural: featuregates + listKind: FeatureGateList + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: Feature holds cluster-wide information about feature gates. The + canonical name is `cluster` + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + customNoUpgrade: + description: customNoUpgrade allows the enabling or disabling of any + feature. Turning this feature set on IS NOT SUPPORTED, CANNOT BE UNDONE, + and PREVENTS UPGRADES. Because of its nature, this setting cannot + be validated. If you have any typos or accidentally apply invalid + combinations your cluster may fail in an unrecoverable way. featureSet + must equal "CustomNoUpgrade" must be set to use this field. + type: object + properties: + disabled: + description: disabled is a list of all feature gates that you want + to force off + type: array + items: + type: string + enabled: + description: enabled is a list of all feature gates that you want + to force on + type: array + items: + type: string + nullable: true + featureSet: + description: featureSet changes the list of features in the cluster. The + default is empty. Be very careful adjusting this setting. Turning + on or off features may cause irreversible changes in your cluster + which cannot be undone. + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_image.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_image.crd.yaml new file mode 100644 index 0000000000..edca7327a3 --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_image.crd.yaml @@ -0,0 +1,144 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: images.config.openshift.io +spec: + group: config.openshift.io + scope: Cluster + preserveUnknownField: false + names: + kind: Image + singular: image + plural: images + listKind: ImageList + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: Image governs policies related to imagestream imports and runtime + configuration for external registries. It allows cluster admins to configure + which registries OpenShift is allowed to import images from, extra CA trust + bundles for external registries, and policies to blacklist/whitelist registry + hostnames. When exposing OpenShift's image registry to the public, this also + lets cluster admins specify the external hostname. + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + additionalTrustedCA: + description: additionalTrustedCA is a reference to a ConfigMap containing + additional CAs that should be trusted during imagestream import, pod + image pull, build image pull, and imageregistry pullthrough. The namespace + for this config map is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced config + map + type: string + allowedRegistriesForImport: + description: allowedRegistriesForImport limits the container image registries + that normal users may import images from. Set this list to the registries + that you trust to contain valid Docker images and that you want applications + to be able to import from. Users with permission to create Images + or ImageStreamMappings via the API are not affected by this policy + - typically only administrators or system integrations will have those + permissions. + type: array + items: + description: RegistryLocation contains a location of the registry + specified by the registry domain name. The domain name might include + wildcards, like '*' or '??'. + type: object + properties: + domainName: + description: domainName specifies a domain name for the registry + In case the registry use non-standard (80 or 443) port, the + port should be included in the domain name as well. + type: string + insecure: + description: insecure indicates whether the registry is secure + (https) or insecure (http) By default (if not specified) the + registry is assumed as secure. + type: boolean + externalRegistryHostnames: + description: externalRegistryHostnames provides the hostnames for the + default external image registry. The external hostname should be set + only when the image registry is exposed externally. The first value + is used in 'publicDockerImageRepository' field in ImageStreams. The + value must be in "hostname[:port]" format. + type: array + items: + type: string + registrySources: + description: registrySources contains configuration that determines + how the container runtime should treat individual registries when + accessing images for builds+pods. (e.g. whether or not to allow insecure + access). It does not contain configuration for the internal cluster + registry. + type: object + properties: + allowedRegistries: + description: "allowedRegistries are whitelisted for image pull/push. + All other registries are blocked. \n Only one of BlockedRegistries + or AllowedRegistries may be set." + type: array + items: + type: string + blockedRegistries: + description: "blockedRegistries are blacklisted from image pull/push. + All other registries are allowed. \n Only one of BlockedRegistries + or AllowedRegistries may be set." + type: array + items: + type: string + insecureRegistries: + description: insecureRegistries are registries which do not have + a valid TLS certificates or only support HTTP connections. + type: array + items: + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object + properties: + externalRegistryHostnames: + description: externalRegistryHostnames provides the hostnames for the + default external image registry. The external hostname should be set + only when the image registry is exposed externally. The first value + is used in 'publicDockerImageRepository' field in ImageStreams. The + value must be in "hostname[:port]" format. + type: array + items: + type: string + internalRegistryHostname: + description: internalRegistryHostname sets the hostname for the default + internal image registry. The value must be in "hostname[:port]" format. + This value is set by the image registry operator which controls the + internal registry hostname. For backward compatibility, users can + still use OPENSHIFT_DEFAULT_REGISTRY environment variable but this + setting overrides the environment variable. + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure.crd.yaml new file mode 100644 index 0000000000..03e59e5ea6 --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_infrastructure.crd.yaml @@ -0,0 +1,221 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: infrastructures.config.openshift.io +spec: + group: config.openshift.io + names: + kind: Infrastructure + listKind: InfrastructureList + plural: infrastructures + singular: infrastructure + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: Infrastructure holds cluster-wide information about Infrastructure. The + canonical name is `cluster` + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + cloudConfig: + description: cloudConfig is a reference to a ConfigMap containing the + cloud provider configuration file. This configuration file is used + to configure the Kubernetes cloud provider integration when using + the built-in cloud provider integration or the external cloud controller + manager. The namespace for this config map is openshift-config. + type: object + properties: + key: + description: Key allows pointing to a specific key/value inside + of the configmap. This is useful for logical file references. + type: string + name: + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object + properties: + apiServerInternalURI: + description: apiServerInternalURL is a valid URI with scheme(http/https), + address and port. apiServerInternalURL can be used by components + like kubelets, to contact the Kubernetes API server using the infrastructure + provider rather than Kubernetes networking. + type: string + apiServerURL: + description: apiServerURL is a valid URI with scheme(http/https), address + and port. apiServerURL can be used by components like the web console + to tell users where to find the Kubernetes API. + type: string + etcdDiscoveryDomain: + description: 'etcdDiscoveryDomain is the domain used to fetch the SRV + records for discovering etcd servers and clients. For more info: https://github.com/etcd-io/etcd/blob/329be66e8b3f9e2e6af83c123ff89297e49ebd15/Documentation/op-guide/clustering.md#dns-discovery' + type: string + infrastructureName: + description: infrastructureName uniquely identifies a cluster with a + human friendly name. Once set it should not be changed. Must be of + max length 27 and must have only alphanumeric or hyphen characters. + type: string + platform: + description: "platform is the underlying infrastructure provider for + the cluster. \n Deprecated: Use platformStatus.type instead." + type: string + platformStatus: + description: platformStatus holds status information specific to the + underlying infrastructure provider. + type: object + properties: + aws: + description: AWS contains settings specific to the Amazon Web Services + infrastructure provider. + type: object + properties: + region: + description: region holds the default AWS region for new AWS + resources created by the cluster. + type: string + azure: + description: Azure contains settings specific to the Azure infrastructure + provider. + type: object + properties: + networkResourceGroupName: + description: networkResourceGroupName is the Resource Group + for network resources like the Virtual Network and Subnets + used by the cluster. If empty, the value is same as ResourceGroupName. + type: string + resourceGroupName: + description: resourceGroupName is the Resource Group for new + Azure resources created for the cluster. + type: string + baremetal: + description: BareMetal contains settings specific to the BareMetal + platform. + type: object + properties: + apiServerInternalIP: + description: apiServerInternalIP is an IP address to contact + the Kubernetes API server that can be used by components inside + the cluster, like kubelets using the infrastructure rather + than Kubernetes networking. It is the IP that the Infrastructure.status.apiServerInternalURI + points to. It is the IP for a self-hosted load balancer in + front of the API servers. + type: string + ingressIP: + description: ingressIP is an external IP which routes to the + default ingress controller. The IP is a suitable target of + a wildcard DNS record used to resolve default route host names. + type: string + nodeDNSIP: + description: nodeDNSIP is the IP address for the internal DNS + used by the nodes. Unlike the one managed by the DNS operator, + `NodeDNSIP` provides name resolution for the nodes themselves. + There is no DNS-as-a-service for BareMetal deployments. In + order to minimize necessary changes to the datacenter DNS, + a DNS service is hosted as a static pod to serve those hostnames + to the nodes in the cluster. + type: string + gcp: + description: GCP contains settings specific to the Google Cloud + Platform infrastructure provider. + type: object + properties: + projectID: + description: resourceGroupName is the Project ID for new GCP + resources created for the cluster. + type: string + region: + description: region holds the region for new GCP resources created + for the cluster. + type: string + openstack: + description: OpenStack contains settings specific to the OpenStack + infrastructure provider. + type: object + properties: + apiServerInternalIP: + description: apiServerInternalIP is an IP address to contact + the Kubernetes API server that can be used by components inside + the cluster, like kubelets using the infrastructure rather + than Kubernetes networking. It is the IP that the Infrastructure.status.apiServerInternalURI + points to. It is the IP for a self-hosted load balancer in + front of the API servers. + type: string + cloudName: + description: cloudName is the name of the desired OpenStack + cloud in the client configuration file (`clouds.yaml`). + type: string + ingressIP: + description: ingressIP is an external IP which routes to the + default ingress controller. The IP is a suitable target of + a wildcard DNS record used to resolve default route host names. + type: string + nodeDNSIP: + description: nodeDNSIP is the IP address for the internal DNS + used by the nodes. Unlike the one managed by the DNS operator, + `NodeDNSIP` provides name resolution for the nodes themselves. + There is no DNS-as-a-service for OpenStack deployments. In + order to minimize necessary changes to the datacenter DNS, + a DNS service is hosted as a static pod to serve those hostnames + to the nodes in the cluster. + type: string + ovirt: + description: Ovirt contains settings specific to the oVirt infrastructure + provider. + type: object + properties: + apiServerInternalIP: + description: apiServerInternalIP is an IP address to contact + the Kubernetes API server that can be used by components inside + the cluster, like kubelets using the infrastructure rather + than Kubernetes networking. It is the IP that the Infrastructure.status.apiServerInternalURI + points to. It is the IP for a self-hosted load balancer in + front of the API servers. + type: string + ingressIP: + description: ingressIP is an external IP which routes to the + default ingress controller. The IP is a suitable target of + a wildcard DNS record used to resolve default route host names. + type: string + nodeDNSIP: + description: nodeDNSIP is the IP address for the internal DNS + used by the nodes. Unlike the one managed by the DNS operator, + `NodeDNSIP` provides name resolution for the nodes themselves. + There is no DNS-as-a-service for oVirt deployments. In order + to minimize necessary changes to the datacenter DNS, a DNS + service is hosted as a static pod to serve those hostnames + to the nodes in the cluster. + type: string + type: + description: type is the underlying infrastructure provider for + the cluster. This value controls whether infrastructure automation + such as service load balancers, dynamic volume provisioning, machine + creation and deletion, and other integrations are enabled. If + None, no infrastructure automation is enabled. Allowed values + are "AWS", "Azure", "BareMetal", "GCP", "Libvirt", "OpenStack", + "VSphere", "oVirt", and "None". Individual components may not + support all platforms, and must handle unrecognized platforms + as None if they do not support that platform. + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_ingress.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_ingress.crd.yaml new file mode 100644 index 0000000000..1505254e3b --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_ingress.crd.yaml @@ -0,0 +1,55 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: ingresses.config.openshift.io +spec: + group: config.openshift.io + names: + kind: Ingress + listKind: IngressList + plural: ingresses + singular: ingress + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: Ingress holds cluster-wide information about ingress, including + the default ingress domain used for routes. The canonical name is `cluster`. + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + domain: + description: "domain is used to generate a default host name for a route + when the route's host name is empty. The generated host name will + follow this pattern: \"..\". + \n It is also used as the default wildcard domain suffix for ingress. + The default ingresscontroller domain will follow this pattern: \"*.\". + \n Once set, changing domain is not currently supported." + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_network.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_network.crd.yaml new file mode 100644 index 0000000000..2335dd8e7e --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_network.crd.yaml @@ -0,0 +1,141 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: networks.config.openshift.io +spec: + group: config.openshift.io + names: + kind: Network + listKind: NetworkList + plural: networks + singular: network + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: 'Network holds cluster-wide information about Network. The canonical + name is `cluster`. It is used to configure the desired network configuration, + such as: IP address pools for services/pod IPs, network plugin, etc. Please + view network.spec for an explanation on what applies when configuring this + resource.' + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration. As a general + rule, this SHOULD NOT be read directly. Instead, you should consume the + NetworkStatus, as it indicates the currently deployed configuration. Currently, + most spec fields are immutable after installation. Please view the individual + ones for further details on each. + type: object + properties: + clusterNetwork: + description: IP address pool to use for pod IPs. This field is immutable + after installation. + type: array + items: + description: ClusterNetworkEntry is a contiguous block of IP addresses + from which pod IPs are allocated. + type: object + properties: + cidr: + description: The complete block for pod IPs. + type: string + hostPrefix: + description: The size (prefix) of block to allocate to each node. + type: integer + format: int32 + minimum: 0 + externalIP: + description: externalIP defines configuration for controllers that affect + Service.ExternalIP. If nil, then ExternalIP is not allowed to be set. + type: object + properties: + autoAssignCIDRs: + description: autoAssignCIDRs is a list of CIDRs from which to automatically + assign Service.ExternalIP. These are assigned when the service + is of type LoadBalancer. In general, this is only useful for bare-metal + clusters. In Openshift 3.x, this was misleadingly called "IngressIPs". + Automatically assigned External IPs are not affected by any ExternalIPPolicy + rules. Currently, only one entry may be provided. + type: array + items: + type: string + policy: + description: policy is a set of restrictions applied to the ExternalIP + field. If nil or empty, then ExternalIP is not allowed to be set. + type: object + properties: + allowedCIDRs: + description: allowedCIDRs is the list of allowed CIDRs. + type: array + items: + type: string + rejectedCIDRs: + description: rejectedCIDRs is the list of disallowed CIDRs. + These take precedence over allowedCIDRs. + type: array + items: + type: string + networkType: + description: 'NetworkType is the plugin that is to be deployed (e.g. + OpenShiftSDN). This should match a value that the cluster-network-operator + understands, or else no networking will be installed. Currently supported + values are: - OpenShiftSDN This field is immutable after installation.' + type: string + serviceNetwork: + description: IP address pool for services. Currently, we only support + a single entry here. This field is immutable after installation. + type: array + items: + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object + properties: + clusterNetwork: + description: IP address pool to use for pod IPs. + type: array + items: + description: ClusterNetworkEntry is a contiguous block of IP addresses + from which pod IPs are allocated. + type: object + properties: + cidr: + description: The complete block for pod IPs. + type: string + hostPrefix: + description: The size (prefix) of block to allocate to each node. + type: integer + format: int32 + minimum: 0 + clusterNetworkMTU: + description: ClusterNetworkMTU is the MTU for inter-pod networking. + type: integer + networkType: + description: NetworkType is the plugin that is deployed (e.g. OpenShiftSDN). + type: string + serviceNetwork: + description: IP address pool for services. Currently, we only support + a single entry here. + type: array + items: + type: string diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_oauth.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_oauth.crd.yaml new file mode 100644 index 0000000000..acc4fbb133 --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_oauth.crd.yaml @@ -0,0 +1,661 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: oauths.config.openshift.io +spec: + group: config.openshift.io + names: + kind: OAuth + listKind: OAuthList + plural: oauths + singular: oauth + scope: Cluster + preserveUnknownField: false + subresources: + status: {} + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: OAuth holds cluster-wide information about OAuth. The canonical + name is `cluster`. It is used to configure the integrated OAuth server. This + configuration is only honored when the top level Authentication config has + type set to IntegratedOAuth. + type: object + required: + - spec + 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: + description: OAuthSpec contains desired cluster auth configuration + type: object + properties: + identityProviders: + description: identityProviders is an ordered list of ways for a user + to identify themselves. When this list is empty, no identities are + provisioned for users. + type: array + items: + description: IdentityProvider provides identities for users authenticating + using credentials + type: object + properties: + basicAuth: + description: basicAuth contains configuration options for the + BasicAuth IdP + type: object + properties: + ca: + description: ca is an optional reference to a config map by + name containing the PEM-encoded CA bundle. It is used as + a trust anchor to validate the TLS certificate presented + by the remote server. The key "ca.crt" is used to locate + the data. If specified and the config map or expected key + is not found, the identity provider is not honored. If the + specified ca data is not valid, the identity provider is + not honored. If empty, the default system roots are used. + The namespace for this config map is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + tlsClientCert: + description: tlsClientCert is an optional reference to a secret + by name that contains the PEM-encoded TLS client certificate + to present when connecting to the server. The key "tls.crt" + is used to locate the data. If specified and the secret + or expected key is not found, the identity provider is not + honored. If the specified certificate data is not valid, + the identity provider is not honored. The namespace for + this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + tlsClientKey: + description: tlsClientKey is an optional reference to a secret + by name that contains the PEM-encoded TLS private key for + the client certificate referenced in tlsClientCert. The + key "tls.key" is used to locate the data. If specified and + the secret or expected key is not found, the identity provider + is not honored. If the specified certificate data is not + valid, the identity provider is not honored. The namespace + for this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + url: + description: url is the remote URL to connect to + type: string + github: + description: github enables user authentication using GitHub credentials + type: object + properties: + ca: + description: ca is an optional reference to a config map by + name containing the PEM-encoded CA bundle. It is used as + a trust anchor to validate the TLS certificate presented + by the remote server. The key "ca.crt" is used to locate + the data. If specified and the config map or expected key + is not found, the identity provider is not honored. If the + specified ca data is not valid, the identity provider is + not honored. If empty, the default system roots are used. + This can only be configured when hostname is set to a non-empty + value. The namespace for this config map is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + clientID: + description: clientID is the oauth client ID + type: string + clientSecret: + description: clientSecret is a required reference to the secret + by name containing the oauth client secret. The key "clientSecret" + is used to locate the data. If the secret or expected key + is not found, the identity provider is not honored. The + namespace for this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + hostname: + description: hostname is the optional domain (e.g. "mycompany.com") + for use with a hosted instance of GitHub Enterprise. It + must match the GitHub Enterprise settings value configured + at /setup/settings#hostname. + type: string + organizations: + description: organizations optionally restricts which organizations + are allowed to log in + type: array + items: + type: string + teams: + description: teams optionally restricts which teams are allowed + to log in. Format is /. + type: array + items: + type: string + gitlab: + description: gitlab enables user authentication using GitLab credentials + type: object + properties: + ca: + description: ca is an optional reference to a config map by + name containing the PEM-encoded CA bundle. It is used as + a trust anchor to validate the TLS certificate presented + by the remote server. The key "ca.crt" is used to locate + the data. If specified and the config map or expected key + is not found, the identity provider is not honored. If the + specified ca data is not valid, the identity provider is + not honored. If empty, the default system roots are used. + The namespace for this config map is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + clientID: + description: clientID is the oauth client ID + type: string + clientSecret: + description: clientSecret is a required reference to the secret + by name containing the oauth client secret. The key "clientSecret" + is used to locate the data. If the secret or expected key + is not found, the identity provider is not honored. The + namespace for this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + url: + description: url is the oauth server base URL + type: string + google: + description: google enables user authentication using Google credentials + type: object + properties: + clientID: + description: clientID is the oauth client ID + type: string + clientSecret: + description: clientSecret is a required reference to the secret + by name containing the oauth client secret. The key "clientSecret" + is used to locate the data. If the secret or expected key + is not found, the identity provider is not honored. The + namespace for this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + hostedDomain: + description: hostedDomain is the optional Google App domain + (e.g. "mycompany.com") to restrict logins to + type: string + htpasswd: + description: htpasswd enables user authentication using an HTPasswd + file to validate credentials + type: object + properties: + fileData: + description: fileData is a required reference to a secret + by name containing the data to use as the htpasswd file. + The key "htpasswd" is used to locate the data. If the secret + or expected key is not found, the identity provider is not + honored. If the specified htpasswd data is not valid, the + identity provider is not honored. The namespace for this + secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + keystone: + description: keystone enables user authentication using keystone + password credentials + type: object + properties: + ca: + description: ca is an optional reference to a config map by + name containing the PEM-encoded CA bundle. It is used as + a trust anchor to validate the TLS certificate presented + by the remote server. The key "ca.crt" is used to locate + the data. If specified and the config map or expected key + is not found, the identity provider is not honored. If the + specified ca data is not valid, the identity provider is + not honored. If empty, the default system roots are used. + The namespace for this config map is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + domainName: + description: domainName is required for keystone v3 + type: string + tlsClientCert: + description: tlsClientCert is an optional reference to a secret + by name that contains the PEM-encoded TLS client certificate + to present when connecting to the server. The key "tls.crt" + is used to locate the data. If specified and the secret + or expected key is not found, the identity provider is not + honored. If the specified certificate data is not valid, + the identity provider is not honored. The namespace for + this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + tlsClientKey: + description: tlsClientKey is an optional reference to a secret + by name that contains the PEM-encoded TLS private key for + the client certificate referenced in tlsClientCert. The + key "tls.key" is used to locate the data. If specified and + the secret or expected key is not found, the identity provider + is not honored. If the specified certificate data is not + valid, the identity provider is not honored. The namespace + for this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + url: + description: url is the remote URL to connect to + type: string + ldap: + description: ldap enables user authentication using LDAP credentials + type: object + properties: + attributes: + description: attributes maps LDAP attributes to identities + type: object + properties: + email: + description: email is the list of attributes whose values + should be used as the email address. Optional. If unspecified, + no email is set for the identity + type: array + items: + type: string + id: + description: id is the list of attributes whose values + should be used as the user ID. Required. First non-empty + attribute is used. At least one attribute is required. + If none of the listed attribute have a value, authentication + fails. LDAP standard identity attribute is "dn" + type: array + items: + type: string + name: + description: name is the list of attributes whose values + should be used as the display name. Optional. If unspecified, + no display name is set for the identity LDAP standard + display name attribute is "cn" + type: array + items: + type: string + preferredUsername: + description: preferredUsername is the list of attributes + whose values should be used as the preferred username. + LDAP standard login attribute is "uid" + type: array + items: + type: string + bindDN: + description: bindDN is an optional DN to bind with during + the search phase. + type: string + bindPassword: + description: bindPassword is an optional reference to a secret + by name containing a password to bind with during the search + phase. The key "bindPassword" is used to locate the data. + If specified and the secret or expected key is not found, + the identity provider is not honored. The namespace for + this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + ca: + description: ca is an optional reference to a config map by + name containing the PEM-encoded CA bundle. It is used as + a trust anchor to validate the TLS certificate presented + by the remote server. The key "ca.crt" is used to locate + the data. If specified and the config map or expected key + is not found, the identity provider is not honored. If the + specified ca data is not valid, the identity provider is + not honored. If empty, the default system roots are used. + The namespace for this config map is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + insecure: + description: 'insecure, if true, indicates the connection + should not use TLS WARNING: Should not be set to `true` + with the URL scheme "ldaps://" as "ldaps://" URLs always attempt + to connect using TLS, even when `insecure` is set to `true` + When `true`, "ldap://" URLS connect insecurely. When `false`, + "ldap://" URLs are upgraded to a TLS connection using StartTLS + as specified in https://tools.ietf.org/html/rfc2830.' + type: boolean + url: + description: 'url is an RFC 2255 URL which specifies the LDAP + search parameters to use. The syntax of the URL is: ldap://host:port/basedn?attribute?scope?filter' + type: string + mappingMethod: + description: mappingMethod determines how identities from this + provider are mapped to users Defaults to "claim" + type: string + name: + description: 'name is used to qualify the identities returned + by this provider. - It MUST be unique and not shared by any + other identity provider used - It MUST be a valid path segment: + name cannot equal "." or ".." or contain "/" or "%" or ":" Ref: + https://godoc.org/github.com/openshift/origin/pkg/user/apis/user/validation#ValidateIdentityProviderName' + type: string + openID: + description: openID enables user authentication using OpenID credentials + type: object + properties: + ca: + description: ca is an optional reference to a config map by + name containing the PEM-encoded CA bundle. It is used as + a trust anchor to validate the TLS certificate presented + by the remote server. The key "ca.crt" is used to locate + the data. If specified and the config map or expected key + is not found, the identity provider is not honored. If the + specified ca data is not valid, the identity provider is + not honored. If empty, the default system roots are used. + The namespace for this config map is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + claims: + description: claims mappings + type: object + properties: + email: + description: email is the list of claims whose values + should be used as the email address. Optional. If unspecified, + no email is set for the identity + type: array + items: + type: string + name: + description: name is the list of claims whose values should + be used as the display name. Optional. If unspecified, + no display name is set for the identity + type: array + items: + type: string + preferredUsername: + description: preferredUsername is the list of claims whose + values should be used as the preferred username. If + unspecified, the preferred username is determined from + the value of the sub claim + type: array + items: + type: string + clientID: + description: clientID is the oauth client ID + type: string + clientSecret: + description: clientSecret is a required reference to the secret + by name containing the oauth client secret. The key "clientSecret" + is used to locate the data. If the secret or expected key + is not found, the identity provider is not honored. The + namespace for this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + secret + type: string + extraAuthorizeParameters: + description: extraAuthorizeParameters are any custom parameters + to add to the authorize request. + type: object + additionalProperties: + type: string + extraScopes: + description: extraScopes are any scopes to request in addition + to the standard "openid" scope. + type: array + items: + type: string + issuer: + description: issuer is the URL that the OpenID Provider asserts + as its Issuer Identifier. It must use the https scheme with + no query or fragment component. + type: string + requestHeader: + description: requestHeader enables user authentication using request + header credentials + type: object + properties: + ca: + description: ca is a required reference to a config map by + name containing the PEM-encoded CA bundle. It is used as + a trust anchor to validate the TLS certificate presented + by the remote server. Specifically, it allows verification + of incoming requests to prevent header spoofing. The key + "ca.crt" is used to locate the data. If the config map or + expected key is not found, the identity provider is not + honored. If the specified ca data is not valid, the identity + provider is not honored. The namespace for this config map + is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced + config map + type: string + challengeURL: + description: challengeURL is a URL to redirect unauthenticated + /authorize requests to Unauthenticated requests from OAuth + clients which expect WWW-Authenticate challenges will be + redirected here. ${url} is replaced with the current URL, + escaped to be safe in a query parameter https://www.example.com/sso-login?then=${url} + ${query} is replaced with the current query string https://www.example.com/auth-proxy/oauth/authorize?${query} + Required when challenge is set to true. + type: string + clientCommonNames: + description: clientCommonNames is an optional list of common + names to require a match from. If empty, any client certificate + validated against the clientCA bundle is considered authoritative. + type: array + items: + type: string + emailHeaders: + description: emailHeaders is the set of headers to check for + the email address + type: array + items: + type: string + headers: + description: headers is the set of headers to check for identity + information + type: array + items: + type: string + loginURL: + description: loginURL is a URL to redirect unauthenticated + /authorize requests to Unauthenticated requests from OAuth + clients which expect interactive logins will be redirected + here ${url} is replaced with the current URL, escaped to + be safe in a query parameter https://www.example.com/sso-login?then=${url} + ${query} is replaced with the current query string https://www.example.com/auth-proxy/oauth/authorize?${query} + Required when login is set to true. + type: string + nameHeaders: + description: nameHeaders is the set of headers to check for + the display name + type: array + items: + type: string + preferredUsernameHeaders: + description: preferredUsernameHeaders is the set of headers + to check for the preferred username + type: array + items: + type: string + type: + description: type identifies the identity provider type for this + entry. + type: string + templates: + description: templates allow you to customize pages like the login page. + type: object + properties: + error: + description: error is the name of a secret that specifies a go template + to use to render error pages during the authentication or grant + flow. The key "errors.html" is used to locate the template data. + If specified and the secret or expected key is not found, the + default error page is used. If the specified template is not valid, + the default error page is used. If unspecified, the default error + page is used. The namespace for this secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced secret + type: string + login: + description: login is the name of a secret that specifies a go template + to use to render the login page. The key "login.html" is used + to locate the template data. If specified and the secret or expected + key is not found, the default login page is used. If the specified + template is not valid, the default login page is used. If unspecified, + the default login page is used. The namespace for this secret + is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced secret + type: string + providerSelection: + description: providerSelection is the name of a secret that specifies + a go template to use to render the provider selection page. The + key "providers.html" is used to locate the template data. If specified + and the secret or expected key is not found, the default provider + selection page is used. If the specified template is not valid, + the default provider selection page is used. If unspecified, the + default provider selection page is used. The namespace for this + secret is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced secret + type: string + tokenConfig: + description: tokenConfig contains options for authorization and access + tokens + type: object + properties: + accessTokenInactivityTimeoutSeconds: + description: 'accessTokenInactivityTimeoutSeconds defines the default + token inactivity timeout for tokens granted by any client. The + value represents the maximum amount of time that can occur between + consecutive uses of the token. Tokens become invalid if they are + not used within this temporal window. The user will need to acquire + a new token to regain access once a token times out. Valid values + are integer values: x < 0 Tokens time out is enabled but tokens + never timeout unless configured per client (e.g. `-1`) x = 0 Tokens + time out is disabled (default) x > 0 Tokens time out if there + is no activity for x seconds The current minimum allowed value + for X is 300 (5 minutes)' + type: integer + format: int32 + accessTokenMaxAgeSeconds: + description: accessTokenMaxAgeSeconds defines the maximum age of + access tokens + type: integer + format: int32 + status: + description: OAuthStatus shows current known state of OAuth server in the + cluster + type: object diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_project.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_project.crd.yaml new file mode 100644 index 0000000000..2361b3563f --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_project.crd.yaml @@ -0,0 +1,63 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: projects.config.openshift.io +spec: + group: config.openshift.io + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + names: + kind: Project + listKind: ProjectList + plural: projects + singular: project + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: Project holds cluster-wide information about Project. The canonical + name is `cluster` + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + projectRequestMessage: + description: projectRequestMessage is the string presented to a user + if they are unable to request a project via the projectrequest api + endpoint + type: string + projectRequestTemplate: + description: projectRequestTemplate is the template to use for creating + projects in response to projectrequest. This must point to a template + in 'openshift-config' namespace. It is optional. If it is not specified, + a default template is used. + type: object + properties: + name: + description: name is the metadata.name of the referenced project + request template + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object diff --git a/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_scheduler.crd.yaml b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_scheduler.crd.yaml new file mode 100644 index 0000000000..9ba0956ba3 --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/0000_10_config-operator_01_scheduler.crd.yaml @@ -0,0 +1,88 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: schedulers.config.openshift.io +spec: + group: config.openshift.io + scope: Cluster + preserveUnknownField: false + names: + kind: Scheduler + singular: scheduler + plural: schedulers + listKind: SchedulerList + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: Scheduler holds cluster-wide config information to run the Kubernetes + Scheduler and influence its placement decisions. The canonical name for this + config is `cluster`. + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + defaultNodeSelector: + description: 'defaultNodeSelector helps set the cluster-wide default + node selector to restrict pod placement to specific nodes. This is + applied to the pods created in all namespaces without a specified + nodeSelector value. For example, defaultNodeSelector: "type=user-node,region=east" + would set nodeSelector field in pod spec to "type=user-node,region=east" + to all pods created in all namespaces. Namespaces having project-wide + node selectors won''t be impacted even if this field is set. This + adds an annotation section to the namespace. For example, if a new + namespace is created with node-selector=''type=user-node,region=east'', + the annotation openshift.io/node-selector: type=user-node,region=east + gets added to the project. When the openshift.io/node-selector annotation + is set on the project the value is used in preference to the value + we are setting for defaultNodeSelector field. For instance, openshift.io/node-selector: + "type=user-node,region=west" means that the default of "type=user-node,region=east" + set in defaultNodeSelector would not be applied.' + type: string + mastersSchedulable: + description: 'MastersSchedulable allows masters nodes to be schedulable. + When this flag is turned on, all the master nodes in the cluster will + be made schedulable, so that workload pods can run on them. The default + value for this field is false, meaning none of the master nodes are + schedulable. Important Note: Once the workload pods start running + on the master nodes, extreme care must be taken to ensure that cluster-critical + control plane components are not impacted. Please turn on this field + after doing due diligence.' + type: boolean + policy: + description: policy is a reference to a ConfigMap containing scheduler + policy which has user specified predicates and priorities. If this + ConfigMap is not available scheduler will default to use DefaultAlgorithmProvider. + The namespace for this configmap is openshift-config. + type: object + required: + - name + properties: + name: + description: name is the metadata.name of the referenced config + map + type: string + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object diff --git a/vendor/github.com/openshift/api/config/v1/types.go b/vendor/github.com/openshift/api/config/v1/types.go index ca36f67775..dcec0ccf5d 100644 --- a/vendor/github.com/openshift/api/config/v1/types.go +++ b/vendor/github.com/openshift/api/config/v1/types.go @@ -167,6 +167,7 @@ type AdmissionPluginConfig struct { // Configuration is an embedded configuration object to be used as the plugin's // configuration. If present, it will be used instead of the path to the configuration file. // +nullable + // +kubebuilder:validation:PreserveUnknownFields Configuration runtime.RawExtension `json:"configuration"` } @@ -210,6 +211,7 @@ type AuditConfig struct { // as the audit policy configuration. If present, it will be used instead of // the path to the policy file. // +nullable + // +kubebuilder:validation:PreserveUnknownFields PolicyConfiguration runtime.RawExtension `json:"policyConfiguration"` // Format of saved audits (legacy or json). diff --git a/vendor/github.com/openshift/api/config/v1/types_apiserver.go b/vendor/github.com/openshift/api/config/v1/types_apiserver.go index 452a090063..741db61f6b 100644 --- a/vendor/github.com/openshift/api/config/v1/types_apiserver.go +++ b/vendor/github.com/openshift/api/config/v1/types_apiserver.go @@ -42,6 +42,11 @@ type APIServerSpec struct { // encryption allows the configuration of encryption of resources at the datastore layer. // +optional Encryption APIServerEncryption `json:"encryption"` + // tlsSecurityProfile specifies settings for TLS connections for externally exposed servers. + // + // If unset, a default (which may change between releases) is chosen. + // +optional + TLSSecurityProfile *TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"` } type APIServerServingCerts struct { diff --git a/vendor/github.com/openshift/api/config/v1/types_authentication.go b/vendor/github.com/openshift/api/config/v1/types_authentication.go index 0722ddbfc7..eecfe75e7c 100644 --- a/vendor/github.com/openshift/api/config/v1/types_authentication.go +++ b/vendor/github.com/openshift/api/config/v1/types_authentication.go @@ -9,8 +9,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Authentication specifies cluster-wide settings for authentication (like OAuth and // webhook token authenticators). The canonical name of an instance is `cluster`. type Authentication struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -77,7 +76,6 @@ type AuthenticationStatus struct { type AuthenticationList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` Items []Authentication `json:"items"` diff --git a/vendor/github.com/openshift/api/config/v1/types_build.go b/vendor/github.com/openshift/api/config/v1/types_build.go index fa4088ca7e..ef4512aa17 100644 --- a/vendor/github.com/openshift/api/config/v1/types_build.go +++ b/vendor/github.com/openshift/api/config/v1/types_build.go @@ -16,6 +16,7 @@ import ( type Build struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` + // Spec holds user-settable values for the build controller configuration // +kubebuilder:validation:Required // +required @@ -102,7 +103,7 @@ type BuildOverrides struct { type BuildList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Build `json:"items"` + + Items []Build `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_cluster_operator.go b/vendor/github.com/openshift/api/config/v1/types_cluster_operator.go index af2ce846ca..f29fe54901 100644 --- a/vendor/github.com/openshift/api/config/v1/types_cluster_operator.go +++ b/vendor/github.com/openshift/api/config/v1/types_cluster_operator.go @@ -57,6 +57,7 @@ type ClusterOperatorStatus struct { // operator which owns this status object. // +nullable // +optional + // +kubebuilder:validation:PreserveUnknownFields Extension runtime.RawExtension `json:"extension"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_console.go b/vendor/github.com/openshift/api/config/v1/types_console.go index 9cda3f83b6..22b0b5160a 100644 --- a/vendor/github.com/openshift/api/config/v1/types_console.go +++ b/vendor/github.com/openshift/api/config/v1/types_console.go @@ -10,8 +10,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // logout URL, and reports the public URL of the console. The canonical name is // `cluster`. type Console struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -40,9 +39,9 @@ type ConsoleStatus struct { type ConsoleList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Console `json:"items"` + + Items []Console `json:"items"` } // ConsoleAuthentication defines a list of optional configuration for console authentication. @@ -58,6 +57,6 @@ type ConsoleAuthentication struct { // provides the user the option to perform single logout (SLO) through the identity // provider to destroy their single sign-on session. // +optional - // +kubebuilder:validation:Pattern=^$|^((https):\/\/?)[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/?))$ + // +kubebuilder:validation:Pattern=`^$|^((https):\/\/?)[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|\/?))$` LogoutRedirect string `json:"logoutRedirect,omitempty"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_dns.go b/vendor/github.com/openshift/api/config/v1/types_dns.go index ef04f7a67f..989ef99c3c 100644 --- a/vendor/github.com/openshift/api/config/v1/types_dns.go +++ b/vendor/github.com/openshift/api/config/v1/types_dns.go @@ -8,8 +8,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // DNS holds cluster-wide information about DNS. The canonical name is `cluster` type DNS struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -82,7 +81,7 @@ type DNSStatus struct { type DNSList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []DNS `json:"items"` + + Items []DNS `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_feature.go b/vendor/github.com/openshift/api/config/v1/types_feature.go index 4a28bb0d16..0dceba6b32 100644 --- a/vendor/github.com/openshift/api/config/v1/types_feature.go +++ b/vendor/github.com/openshift/api/config/v1/types_feature.go @@ -8,8 +8,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Feature holds cluster-wide information about feature gates. The canonical name is `cluster` type FeatureGate struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -76,9 +75,9 @@ type FeatureGateStatus struct { type FeatureGateList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []FeatureGate `json:"items"` + + Items []FeatureGate `json:"items"` } type FeatureGateEnabledDisabled struct { @@ -103,9 +102,12 @@ var FeatureSets = map[FeatureSet]*FeatureGateEnabledDisabled{ "ExperimentalCriticalPodAnnotation", // sig-pod, sjenning "RotateKubeletServerCertificate", // sig-pod, sjenning "SupportPodPidsLimit", // sig-pod, sjenning + "TLSSecurityProfile", // sig-network, danehans + "NodeDisruptionExclusion", // sig-scheduling, ccoleman + "ServiceNodeExclusion", // sig-scheduling, ccoleman }, Disabled: []string{ - "LocalStorageCapacityIsolation", // sig-pod, sjenning + "LegacyNodeRoleBehavior", // sig-scheduling, ccoleman }, }, CustomNoUpgrade: { @@ -117,9 +119,12 @@ var FeatureSets = map[FeatureSet]*FeatureGateEnabledDisabled{ "ExperimentalCriticalPodAnnotation", // sig-pod, sjenning "RotateKubeletServerCertificate", // sig-pod, sjenning "SupportPodPidsLimit", // sig-pod, sjenning + "TLSSecurityProfile", // sig-network, danehans + "NodeDisruptionExclusion", // sig-scheduling, ccoleman + "ServiceNodeExclusion", // sig-scheduling, ccoleman }, Disabled: []string{ - "LocalStorageCapacityIsolation", // sig-pod, sjenning + "LegacyNodeRoleBehavior", // sig-scheduling, ccoleman }, }, LatencySensitive: { @@ -128,9 +133,11 @@ var FeatureSets = map[FeatureSet]*FeatureGateEnabledDisabled{ "RotateKubeletServerCertificate", // sig-pod, sjenning "SupportPodPidsLimit", // sig-pod, sjenning "TopologyManager", // sig-pod, sjenning + "NodeDisruptionExclusion", // sig-scheduling, ccoleman + "ServiceNodeExclusion", // sig-scheduling, ccoleman }, Disabled: []string{ - "LocalStorageCapacityIsolation", // sig-pod, sjenning + "LegacyNodeRoleBehavior", // sig-scheduling, ccoleman }, }, } diff --git a/vendor/github.com/openshift/api/config/v1/types_image.go b/vendor/github.com/openshift/api/config/v1/types_image.go index 94eb741167..bf594c1b77 100644 --- a/vendor/github.com/openshift/api/config/v1/types_image.go +++ b/vendor/github.com/openshift/api/config/v1/types_image.go @@ -13,8 +13,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // When exposing OpenShift's image registry to the public, this also lets cluster // admins specify the external hostname. type Image struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -80,9 +79,9 @@ type ImageStatus struct { type ImageList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Image `json:"items"` + + Items []Image `json:"items"` } // RegistryLocation contains a location of the registry specified by the registry domain diff --git a/vendor/github.com/openshift/api/config/v1/types_infrastructure.go b/vendor/github.com/openshift/api/config/v1/types_infrastructure.go index 4632e6ada0..ac1e5048ee 100644 --- a/vendor/github.com/openshift/api/config/v1/types_infrastructure.go +++ b/vendor/github.com/openshift/api/config/v1/types_infrastructure.go @@ -8,8 +8,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Infrastructure holds cluster-wide information about Infrastructure. The canonical name is `cluster` type Infrastructure struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -130,6 +129,10 @@ type PlatformStatus struct { // OpenStack contains settings specific to the OpenStack infrastructure provider. // +optional OpenStack *OpenStackPlatformStatus `json:"openstack,omitempty"` + + // Ovirt contains settings specific to the oVirt infrastructure provider. + // +optional + Ovirt *OvirtPlatformStatus `json:"ovirt,omitempty"` } // AWSPlatformStatus holds the current status of the Amazon Web Services infrastructure provider. @@ -142,6 +145,11 @@ type AWSPlatformStatus struct { type AzurePlatformStatus struct { // resourceGroupName is the Resource Group for new Azure resources created for the cluster. ResourceGroupName string `json:"resourceGroupName"` + + // networkResourceGroupName is the Resource Group for network resources like the Virtual Network and Subnets used by the cluster. + // If empty, the value is same as ResourceGroupName. + // +optional + NetworkResourceGroupName string `json:"networkResourceGroupName,omitempty"` } // GCPPlatformStatus holds the current status of the Google Cloud Platform infrastructure provider. @@ -154,6 +162,8 @@ type GCPPlatformStatus struct { } // BareMetalPlatformStatus holds the current status of the BareMetal infrastructure provider. +// For more information about the network architecture used with the BareMetal platform type, see: +// https://github.com/openshift/installer/blob/master/docs/design/baremetal/networking-infrastructure.md type BareMetalPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -199,12 +209,33 @@ type OpenStackPlatformStatus struct { NodeDNSIP string `json:"nodeDNSIP,omitempty"` } +// OvirtPlatformStatus holds the current status of the oVirt infrastructure provider. +type OvirtPlatformStatus struct { + // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used + // by components inside the cluster, like kubelets using the infrastructure rather + // than Kubernetes networking. It is the IP that the Infrastructure.status.apiServerInternalURI + // points to. It is the IP for a self-hosted load balancer in front of the API servers. + APIServerInternalIP string `json:"apiServerInternalIP,omitempty"` + + // ingressIP is an external IP which routes to the default ingress controller. + // The IP is a suitable target of a wildcard DNS record used to resolve default route host names. + IngressIP string `json:"ingressIP,omitempty"` + + // nodeDNSIP is the IP address for the internal DNS used by the + // nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` + // provides name resolution for the nodes themselves. There is no DNS-as-a-service for + // oVirt deployments. In order to minimize necessary changes to the + // datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames + // to the nodes in the cluster. + NodeDNSIP string `json:"nodeDNSIP,omitempty"` +} + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // InfrastructureList is type InfrastructureList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Infrastructure `json:"items"` + + Items []Infrastructure `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_ingress.go b/vendor/github.com/openshift/api/config/v1/types_ingress.go index d161eb8476..0216919ad8 100644 --- a/vendor/github.com/openshift/api/config/v1/types_ingress.go +++ b/vendor/github.com/openshift/api/config/v1/types_ingress.go @@ -9,8 +9,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Ingress holds cluster-wide information about ingress, including the default ingress domain // used for routes. The canonical name is `cluster`. type Ingress struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -41,7 +40,7 @@ type IngressStatus struct { type IngressList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Ingress `json:"items"` + + Items []Ingress `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_network.go b/vendor/github.com/openshift/api/config/v1/types_network.go index 9a88fb5d1b..a09c5fe8ed 100644 --- a/vendor/github.com/openshift/api/config/v1/types_network.go +++ b/vendor/github.com/openshift/api/config/v1/types_network.go @@ -9,8 +9,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Network holds cluster-wide information about Network. The canonical name is `cluster`. It is used to configure the desired network configuration, such as: IP address pools for services/pod IPs, network plugin, etc. // Please view network.spec for an explanation on what applies when configuring this resource. type Network struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration. @@ -117,7 +116,7 @@ type ExternalIPPolicy struct { type NetworkList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Network `json:"items"` + + Items []Network `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_operatorhub.go b/vendor/github.com/openshift/api/config/v1/types_operatorhub.go index 31291dec2f..1d998bf37d 100644 --- a/vendor/github.com/openshift/api/config/v1/types_operatorhub.go +++ b/vendor/github.com/openshift/api/config/v1/types_operatorhub.go @@ -70,7 +70,7 @@ type HubSource struct { // HubSourceStatus is used to reflect the current state of applying the // configuration to a default source type HubSourceStatus struct { - HubSource `json:"",omitempty` + HubSource `json:",omitempty"` // status indicates success or failure in applying the configuration Status string `json:"status,omitempty"` // message provides more information regarding failures diff --git a/vendor/github.com/openshift/api/config/v1/types_project.go b/vendor/github.com/openshift/api/config/v1/types_project.go index 61152a6f79..244ce3ef8f 100644 --- a/vendor/github.com/openshift/api/config/v1/types_project.go +++ b/vendor/github.com/openshift/api/config/v1/types_project.go @@ -8,8 +8,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Project holds cluster-wide information about Project. The canonical name is `cluster` type Project struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -49,7 +48,7 @@ type ProjectStatus struct { type ProjectList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Project `json:"items"` + + Items []Project `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_proxy.go b/vendor/github.com/openshift/api/config/v1/types_proxy.go index 1413a48caa..93f4c487e4 100644 --- a/vendor/github.com/openshift/api/config/v1/types_proxy.go +++ b/vendor/github.com/openshift/api/config/v1/types_proxy.go @@ -12,6 +12,7 @@ import ( type Proxy struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` + // Spec holds user-settable values for the proxy configuration // +kubebuilder:validation:Required // +required @@ -83,7 +84,7 @@ type ProxyStatus struct { type ProxyList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Proxy `json:"items"` + + Items []Proxy `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_scheduling.go b/vendor/github.com/openshift/api/config/v1/types_scheduling.go index 9b8fa3a52a..d5bf0c3627 100644 --- a/vendor/github.com/openshift/api/config/v1/types_scheduling.go +++ b/vendor/github.com/openshift/api/config/v1/types_scheduling.go @@ -9,8 +9,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // Scheduler holds cluster-wide config information to run the Kubernetes Scheduler // and influence its placement decisions. The canonical name for this config is `cluster`. type Scheduler struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -69,7 +68,7 @@ type SchedulerStatus struct { type SchedulerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []Scheduler `json:"items"` + + Items []Scheduler `json:"items"` } diff --git a/vendor/github.com/openshift/api/config/v1/types_tlssecurityprofile.go b/vendor/github.com/openshift/api/config/v1/types_tlssecurityprofile.go new file mode 100644 index 0000000000..6ce492003e --- /dev/null +++ b/vendor/github.com/openshift/api/config/v1/types_tlssecurityprofile.go @@ -0,0 +1,233 @@ +package v1 + +// TLSSecurityProfile defines the schema for a TLS security profile. This object +// is used by operators to apply TLS security settings to operands. +// +union +type TLSSecurityProfile struct { + // type is one of Old, Intermediate, Modern or Custom. Custom provides + // the ability to specify individual TLS security profile parameters. + // Old, Intermediate and Modern are TLS security profiles based on: + // + // https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations + // + // The profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers + // are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be + // reduced. + // + // +unionDiscriminator + // +optional + Type TLSProfileType `json:"type"` + // old is a TLS security profile based on: + // + // https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility + // + // and looks like this (yaml): + // + // ciphers: + // - TLS_AES_128_GCM_SHA256 + // - TLS_AES_256_GCM_SHA384 + // - TLS_CHACHA20_POLY1305_SHA256 + // - ECDHE-ECDSA-AES128-GCM-SHA256 + // - ECDHE-RSA-AES128-GCM-SHA256 + // - ECDHE-ECDSA-AES256-GCM-SHA384 + // - ECDHE-RSA-AES256-GCM-SHA384 + // - ECDHE-ECDSA-CHACHA20-POLY1305 + // - ECDHE-RSA-CHACHA20-POLY1305 + // - ECDHE-ECDSA-AES128-SHA256 + // - ECDHE-RSA-AES128-SHA256 + // - ECDHE-ECDSA-AES128-SHA + // - ECDHE-RSA-AES128-SHA + // - ECDHE-ECDSA-AES256-SHA + // - ECDHE-RSA-AES256-SHA + // - AES128-GCM-SHA256 + // - AES256-GCM-SHA384 + // - AES128-SHA256 + // - AES128-SHA + // - AES256-SHA + // - DES-CBC3-SHA + // minTLSVersion: TLSv1.0 + // + // +optional + // +nullable + Old *OldTLSProfile `json:"old,omitempty"` + // intermediate is a TLS security profile based on: + // + // https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29 + // + // and looks like this (yaml): + // + // ciphers: + // - TLS_AES_128_GCM_SHA256 + // - TLS_AES_256_GCM_SHA384 + // - TLS_CHACHA20_POLY1305_SHA256 + // - ECDHE-ECDSA-AES128-GCM-SHA256 + // - ECDHE-RSA-AES128-GCM-SHA256 + // - ECDHE-ECDSA-AES256-GCM-SHA384 + // - ECDHE-RSA-AES256-GCM-SHA384 + // - ECDHE-ECDSA-CHACHA20-POLY1305 + // - ECDHE-RSA-CHACHA20-POLY1305 + // minTLSVersion: TLSv1.2 + // + // +optional + // +nullable + Intermediate *IntermediateTLSProfile `json:"intermediate,omitempty"` + // modern is a TLS security profile based on: + // + // https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility + // + // and looks like this (yaml): + // + // ciphers: + // - TLS_AES_128_GCM_SHA256 + // - TLS_AES_256_GCM_SHA384 + // - TLS_CHACHA20_POLY1305_SHA256 + // minTLSVersion: TLSv1.3 + // + // +optional + // +nullable + Modern *ModernTLSProfile `json:"modern,omitempty"` + // custom is a user-defined TLS security profile. Be extremely careful using a custom + // profile as invalid configurations can be catastrophic. An example custom profile + // looks like this: + // + // ciphers: + // - ECDHE-ECDSA-CHACHA20-POLY1305 + // - ECDHE-RSA-CHACHA20-POLY1305 + // - ECDHE-RSA-AES128-GCM-SHA256 + // - ECDHE-ECDSA-AES128-GCM-SHA256 + // minTLSVersion: TLSv1.1 + // + // +optional + // +nullable + Custom *CustomTLSProfile `json:"custom,omitempty"` +} + +// OldTLSProfile is a TLS security profile based on: +// https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility +type OldTLSProfile struct{} + +// IntermediateTLSProfile is a TLS security profile based on: +// https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 +type IntermediateTLSProfile struct{} + +// ModernTLSProfile is a TLS security profile based on: +// https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility +type ModernTLSProfile struct{} + +// CustomTLSProfile is a user-defined TLS security profile. Be extremely careful +// using a custom TLS profile as invalid configurations can be catastrophic. +type CustomTLSProfile struct { + TLSProfileSpec `json:",inline"` +} + +// TLSProfileType defines a TLS security profile type. +type TLSProfileType string + +const ( + // Old is a TLS security profile based on: + // https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility + TLSProfileOldType TLSProfileType = "Old" + // Intermediate is a TLS security profile based on: + // https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29 + TLSProfileIntermediateType TLSProfileType = "Intermediate" + // Modern is a TLS security profile based on: + // https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility + TLSProfileModernType TLSProfileType = "Modern" + // Custom is a TLS security profile that allows for user-defined parameters. + TLSProfileCustomType TLSProfileType = "Custom" +) + +// TLSProfileSpec is the desired behavior of a TLSSecurityProfile. +type TLSProfileSpec struct { + // ciphers is used to specify the cipher algorithms that are negotiated + // during the TLS handshake. Operators may remove entries their operands + // do not support. For example, to use DES-CBC3-SHA (yaml): + // + // ciphers: + // - DES-CBC3-SHA + // + Ciphers []string `json:"ciphers"` + // minTLSVersion is used to specify the minimal version of the TLS protocol + // that is negotiated during the TLS handshake. For example, to use TLS + // versions 1.1, 1.2 and 1.3 (yaml): + // + // minTLSVersion: TLSv1.1 + // + MinTLSVersion TLSProtocolVersion `json:"minTLSVersion"` +} + +// TLSProtocolVersion is a way to specify the protocol version used for TLS connections. +// Protocol versions are based on the following most common TLS configurations: +// +// https://ssl-config.mozilla.org/ +// +// Note that SSLv3.0 is not a supported protocol version due to well known +// vulnerabilities such as POODLE: https://en.wikipedia.org/wiki/POODLE +type TLSProtocolVersion string + +const ( + // VersionTLSv10 is version 1.0 of the TLS security protocol. + VersionTLS10 TLSProtocolVersion = "VersionTLS10" + // VersionTLSv11 is version 1.1 of the TLS security protocol. + VersionTLS11 TLSProtocolVersion = "VersionTLS11" + // VersionTLSv12 is version 1.2 of the TLS security protocol. + VersionTLS12 TLSProtocolVersion = "VersionTLS12" + // VersionTLSv13 is version 1.3 of the TLS security protocol. + VersionTLS13 TLSProtocolVersion = "VersionTLS13" +) + +// TLSProfiles Contains a map of TLSProfileType names to TLSProfileSpec. +// +// NOTE: The caller needs to make sure to check that these constants are valid for their binary. Not all +// entries map to values for all binaries. In the case of ties, the kube-apiserver wins. Do not fail, +// just be sure to whitelist only and everything will be ok. +var TLSProfiles = map[TLSProfileType]*TLSProfileSpec{ + TLSProfileOldType: { + Ciphers: []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-CHACHA20-POLY1305", + "ECDHE-RSA-CHACHA20-POLY1305", + "ECDHE-ECDSA-AES128-SHA256", + "ECDHE-RSA-AES128-SHA256", + "ECDHE-ECDSA-AES128-SHA", + "ECDHE-RSA-AES128-SHA", + "ECDHE-ECDSA-AES256-SHA", + "ECDHE-RSA-AES256-SHA", + "AES128-GCM-SHA256", + "AES256-GCM-SHA384", + "AES128-SHA256", + "AES128-SHA", + "AES256-SHA", + "DES-CBC3-SHA", + }, + MinTLSVersion: VersionTLS10, + }, + TLSProfileIntermediateType: { + Ciphers: []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", + "ECDHE-ECDSA-AES128-GCM-SHA256", + "ECDHE-RSA-AES128-GCM-SHA256", + "ECDHE-ECDSA-AES256-GCM-SHA384", + "ECDHE-RSA-AES256-GCM-SHA384", + "ECDHE-ECDSA-CHACHA20-POLY1305", + "ECDHE-RSA-CHACHA20-POLY1305", + }, + MinTLSVersion: VersionTLS12, + }, + TLSProfileModernType: { + Ciphers: []string{ + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256", + }, + MinTLSVersion: VersionTLS13, + }, +} diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go index 571be5a908..37888a9395 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go @@ -142,6 +142,11 @@ func (in *APIServerSpec) DeepCopyInto(out *APIServerSpec) { copy(*out, *in) } out.Encryption = in.Encryption + if in.TLSSecurityProfile != nil { + in, out := &in.TLSSecurityProfile, &out.TLSSecurityProfile + *out = new(TLSSecurityProfile) + (*in).DeepCopyInto(*out) + } return } @@ -1039,6 +1044,23 @@ func (in *CustomFeatureGates) DeepCopy() *CustomFeatureGates { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomTLSProfile) DeepCopyInto(out *CustomTLSProfile) { + *out = *in + in.TLSProfileSpec.DeepCopyInto(&out.TLSProfileSpec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomTLSProfile. +func (in *CustomTLSProfile) DeepCopy() *CustomTLSProfile { + if in == nil { + return nil + } + out := new(CustomTLSProfile) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DNS) DeepCopyInto(out *DNS) { *out = *in @@ -2017,6 +2039,22 @@ func (in *IngressStatus) DeepCopy() *IngressStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IntermediateTLSProfile) DeepCopyInto(out *IntermediateTLSProfile) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IntermediateTLSProfile. +func (in *IntermediateTLSProfile) DeepCopy() *IntermediateTLSProfile { + if in == nil { + return nil + } + out := new(IntermediateTLSProfile) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KeystoneIdentityProvider) DeepCopyInto(out *KeystoneIdentityProvider) { *out = *in @@ -2125,6 +2163,22 @@ func (in *LeaderElection) DeepCopy() *LeaderElection { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ModernTLSProfile) DeepCopyInto(out *ModernTLSProfile) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ModernTLSProfile. +func (in *ModernTLSProfile) DeepCopy() *ModernTLSProfile { + if in == nil { + return nil + } + out := new(ModernTLSProfile) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NamedCertificate) DeepCopyInto(out *NamedCertificate) { *out = *in @@ -2421,6 +2475,22 @@ func (in *ObjectReference) DeepCopy() *ObjectReference { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OldTLSProfile) DeepCopyInto(out *OldTLSProfile) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OldTLSProfile. +func (in *OldTLSProfile) DeepCopy() *OldTLSProfile { + if in == nil { + return nil + } + out := new(OldTLSProfile) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OpenIDClaims) DeepCopyInto(out *OpenIDClaims) { *out = *in @@ -2618,6 +2688,22 @@ func (in *OperatorHubStatus) DeepCopy() *OperatorHubStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OvirtPlatformStatus) DeepCopyInto(out *OvirtPlatformStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OvirtPlatformStatus. +func (in *OvirtPlatformStatus) DeepCopy() *OvirtPlatformStatus { + if in == nil { + return nil + } + out := new(OvirtPlatformStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PlatformStatus) DeepCopyInto(out *PlatformStatus) { *out = *in @@ -2646,6 +2732,11 @@ func (in *PlatformStatus) DeepCopyInto(out *PlatformStatus) { *out = new(OpenStackPlatformStatus) **out = **in } + if in.Ovirt != nil { + in, out := &in.Ovirt, &out.Ovirt + *out = new(OvirtPlatformStatus) + **out = **in + } return } @@ -3130,6 +3221,63 @@ func (in *StringSourceSpec) DeepCopy() *StringSourceSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSProfileSpec) DeepCopyInto(out *TLSProfileSpec) { + *out = *in + if in.Ciphers != nil { + in, out := &in.Ciphers, &out.Ciphers + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSProfileSpec. +func (in *TLSProfileSpec) DeepCopy() *TLSProfileSpec { + if in == nil { + return nil + } + out := new(TLSProfileSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSSecurityProfile) DeepCopyInto(out *TLSSecurityProfile) { + *out = *in + if in.Old != nil { + in, out := &in.Old, &out.Old + *out = new(OldTLSProfile) + **out = **in + } + if in.Intermediate != nil { + in, out := &in.Intermediate, &out.Intermediate + *out = new(IntermediateTLSProfile) + **out = **in + } + if in.Modern != nil { + in, out := &in.Modern, &out.Modern + *out = new(ModernTLSProfile) + **out = **in + } + if in.Custom != nil { + in, out := &in.Custom, &out.Custom + *out = new(CustomTLSProfile) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSSecurityProfile. +func (in *TLSSecurityProfile) DeepCopy() *TLSSecurityProfile { + if in == nil { + return nil + } + out := new(TLSSecurityProfile) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TemplateReference) DeepCopyInto(out *TemplateReference) { *out = *in diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go index d48870185e..5652b5a51c 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go @@ -282,6 +282,7 @@ var map_APIServerSpec = map[string]string{ "clientCA": "clientCA references a ConfigMap containing a certificate bundle for the signers that will be recognized for incoming client certificates in addition to the operator managed signers. If this is empty, then only operator managed signers are valid. You usually only have to set this if you have your own PKI you wish to honor client certificates from. The ConfigMap must exist in the openshift-config namespace and contain the following required fields: - ConfigMap.Data[\"ca-bundle.crt\"] - CA bundle.", "additionalCORSAllowedOrigins": "additionalCORSAllowedOrigins lists additional, user-defined regular expressions describing hosts for which the API server allows access using the CORS headers. This may be needed to access the API and the integrated OAuth server from JavaScript applications. The values are regular expressions that correspond to the Golang regular expression language.", "encryption": "encryption allows the configuration of encryption of resources at the datastore layer.", + "tlsSecurityProfile": "tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.\n\nIf unset, a default (which may change between releases) is chosen.", } func (APIServerSpec) SwaggerDoc() map[string]string { @@ -289,24 +290,15 @@ func (APIServerSpec) SwaggerDoc() map[string]string { } var map_Authentication = map[string]string{ - "": "Authentication specifies cluster-wide settings for authentication (like OAuth and webhook token authenticators). The canonical name of an instance is `cluster`.", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Authentication specifies cluster-wide settings for authentication (like OAuth and webhook token authenticators). The canonical name of an instance is `cluster`.", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Authentication) SwaggerDoc() map[string]string { return map_Authentication } -var map_AuthenticationList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (AuthenticationList) SwaggerDoc() map[string]string { - return map_AuthenticationList -} - var map_AuthenticationSpec = map[string]string{ "type": "type identifies the cluster managed, user facing authentication mode in use. Specifically, it manages the component that responds to login attempts. The default is IntegratedOAuth.", "oauthMetadata": "oauthMetadata contains the discovery endpoint data for OAuth 2.0 Authorization Server Metadata for an external OAuth server. This discovery document can be viewed from its served location: oc get --raw '/.well-known/oauth-authorization-server' For further details, see the IETF Draft: https://tools.ietf.org/html/draft-ietf-oauth-discovery-04#section-2 If oauthMetadata.name is non-empty, this value has precedence over any metadata reference stored in status. The key \"oauthMetadata\" is used to locate the data. If specified and the config map or expected key is not found, no metadata is served. If the specified metadata is not valid, no metadata is served. The namespace for this config map is openshift-config.", @@ -355,14 +347,6 @@ func (BuildDefaults) SwaggerDoc() map[string]string { return map_BuildDefaults } -var map_BuildList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (BuildList) SwaggerDoc() map[string]string { - return map_BuildList -} - var map_BuildOverrides = map[string]string{ "imageLabels": "ImageLabels is a list of docker labels that are applied to the resulting image. If user provided a label in their Build/BuildConfig with the same name as one in this list, the user's label will be overwritten.", "nodeSelector": "NodeSelector is a selector which must be true for the build pod to fit on a node", @@ -548,10 +532,9 @@ func (UpdateHistory) SwaggerDoc() map[string]string { } var map_Console = map[string]string{ - "": "Console holds cluster-wide configuration for the web console, including the logout URL, and reports the public URL of the console. The canonical name is `cluster`.", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Console holds cluster-wide configuration for the web console, including the logout URL, and reports the public URL of the console. The canonical name is `cluster`.", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Console) SwaggerDoc() map[string]string { @@ -567,14 +550,6 @@ func (ConsoleAuthentication) SwaggerDoc() map[string]string { return map_ConsoleAuthentication } -var map_ConsoleList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (ConsoleList) SwaggerDoc() map[string]string { - return map_ConsoleList -} - var map_ConsoleSpec = map[string]string{ "": "ConsoleSpec is the specification of the desired behavior of the Console.", } @@ -593,24 +568,15 @@ func (ConsoleStatus) SwaggerDoc() map[string]string { } var map_DNS = map[string]string{ - "": "DNS holds cluster-wide information about DNS. The canonical name is `cluster`", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "DNS holds cluster-wide information about DNS. The canonical name is `cluster`", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (DNS) SwaggerDoc() map[string]string { return map_DNS } -var map_DNSList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (DNSList) SwaggerDoc() map[string]string { - return map_DNSList -} - var map_DNSSpec = map[string]string{ "baseDomain": "baseDomain is the base domain of the cluster. All managed DNS records will be sub-domains of this base.\n\nFor example, given the base domain `openshift.example.com`, an API server DNS record may be created for `cluster-api.openshift.example.com`.\n\nOnce set, this field cannot be changed.", "publicZone": "publicZone is the location where all the DNS records that are publicly accessible to the internet exist.\n\nIf this field is nil, no public records should be created.\n\nOnce set, this field cannot be changed.", @@ -641,24 +607,15 @@ func (CustomFeatureGates) SwaggerDoc() map[string]string { } var map_FeatureGate = map[string]string{ - "": "Feature holds cluster-wide information about feature gates. The canonical name is `cluster`", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Feature holds cluster-wide information about feature gates. The canonical name is `cluster`", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (FeatureGate) SwaggerDoc() map[string]string { return map_FeatureGate } -var map_FeatureGateList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (FeatureGateList) SwaggerDoc() map[string]string { - return map_FeatureGateList -} - var map_FeatureGateSelection = map[string]string{ "featureSet": "featureSet changes the list of features in the cluster. The default is empty. Be very careful adjusting this setting. Turning on or off features may cause irreversible changes in your cluster which cannot be undone.", "customNoUpgrade": "customNoUpgrade allows the enabling or disabling of any feature. Turning this feature set on IS NOT SUPPORTED, CANNOT BE UNDONE, and PREVENTS UPGRADES. Because of its nature, this setting cannot be validated. If you have any typos or accidentally apply invalid combinations your cluster may fail in an unrecoverable way. featureSet must equal \"CustomNoUpgrade\" must be set to use this field.", @@ -669,24 +626,15 @@ func (FeatureGateSelection) SwaggerDoc() map[string]string { } var map_Image = map[string]string{ - "": "Image governs policies related to imagestream imports and runtime configuration for external registries. It allows cluster admins to configure which registries OpenShift is allowed to import images from, extra CA trust bundles for external registries, and policies to blacklist/whitelist registry hostnames. When exposing OpenShift's image registry to the public, this also lets cluster admins specify the external hostname.", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Image governs policies related to imagestream imports and runtime configuration for external registries. It allows cluster admins to configure which registries OpenShift is allowed to import images from, extra CA trust bundles for external registries, and policies to blacklist/whitelist registry hostnames. When exposing OpenShift's image registry to the public, this also lets cluster admins specify the external hostname.", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Image) SwaggerDoc() map[string]string { return map_Image } -var map_ImageList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (ImageList) SwaggerDoc() map[string]string { - return map_ImageList -} - var map_ImageSpec = map[string]string{ "allowedRegistriesForImport": "allowedRegistriesForImport limits the container image registries that normal users may import images from. Set this list to the registries that you trust to contain valid Docker images and that you want applications to be able to import from. Users with permission to create Images or ImageStreamMappings via the API are not affected by this policy - typically only administrators or system integrations will have those permissions.", "externalRegistryHostnames": "externalRegistryHostnames provides the hostnames for the default external image registry. The external hostname should be set only when the image registry is exposed externally. The first value is used in 'publicDockerImageRepository' field in ImageStreams. The value must be in \"hostname[:port]\" format.", @@ -738,8 +686,9 @@ func (AWSPlatformStatus) SwaggerDoc() map[string]string { } var map_AzurePlatformStatus = map[string]string{ - "": "AzurePlatformStatus holds the current status of the Azure infrastructure provider.", - "resourceGroupName": "resourceGroupName is the Resource Group for new Azure resources created for the cluster.", + "": "AzurePlatformStatus holds the current status of the Azure infrastructure provider.", + "resourceGroupName": "resourceGroupName is the Resource Group for new Azure resources created for the cluster.", + "networkResourceGroupName": "networkResourceGroupName is the Resource Group for network resources like the Virtual Network and Subnets used by the cluster. If empty, the value is same as ResourceGroupName.", } func (AzurePlatformStatus) SwaggerDoc() map[string]string { @@ -747,7 +696,7 @@ func (AzurePlatformStatus) SwaggerDoc() map[string]string { } var map_BareMetalPlatformStatus = map[string]string{ - "": "BareMetalPlatformStatus holds the current status of the BareMetal infrastructure provider.", + "": "BareMetalPlatformStatus holds the current status of the BareMetal infrastructure provider. For more information about the network architecture used with the BareMetal platform type, see: https://github.com/openshift/installer/blob/master/docs/design/baremetal/networking-infrastructure.md", "apiServerInternalIP": "apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used by components inside the cluster, like kubelets using the infrastructure rather than Kubernetes networking. It is the IP that the Infrastructure.status.apiServerInternalURI points to. It is the IP for a self-hosted load balancer in front of the API servers.", "ingressIP": "ingressIP is an external IP which routes to the default ingress controller. The IP is a suitable target of a wildcard DNS record used to resolve default route host names.", "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for BareMetal deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", @@ -768,10 +717,9 @@ func (GCPPlatformStatus) SwaggerDoc() map[string]string { } var map_Infrastructure = map[string]string{ - "": "Infrastructure holds cluster-wide information about Infrastructure. The canonical name is `cluster`", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Infrastructure holds cluster-wide information about Infrastructure. The canonical name is `cluster`", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Infrastructure) SwaggerDoc() map[string]string { @@ -779,8 +727,7 @@ func (Infrastructure) SwaggerDoc() map[string]string { } var map_InfrastructureList = map[string]string{ - "": "InfrastructureList is", - "metadata": "Standard object's metadata.", + "": "InfrastructureList is", } func (InfrastructureList) SwaggerDoc() map[string]string { @@ -822,6 +769,17 @@ func (OpenStackPlatformStatus) SwaggerDoc() map[string]string { return map_OpenStackPlatformStatus } +var map_OvirtPlatformStatus = map[string]string{ + "": "OvirtPlatformStatus holds the current status of the oVirt infrastructure provider.", + "apiServerInternalIP": "apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used by components inside the cluster, like kubelets using the infrastructure rather than Kubernetes networking. It is the IP that the Infrastructure.status.apiServerInternalURI points to. It is the IP for a self-hosted load balancer in front of the API servers.", + "ingressIP": "ingressIP is an external IP which routes to the default ingress controller. The IP is a suitable target of a wildcard DNS record used to resolve default route host names.", + "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for oVirt deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", +} + +func (OvirtPlatformStatus) SwaggerDoc() map[string]string { + return map_OvirtPlatformStatus +} + var map_PlatformStatus = map[string]string{ "": "PlatformStatus holds the current status specific to the underlying infrastructure provider of the current cluster. Since these are used at status-level for the underlying cluster, it is supposed that only one of the status structs is set.", "type": "type is the underlying infrastructure provider for the cluster. This value controls whether infrastructure automation such as service load balancers, dynamic volume provisioning, machine creation and deletion, and other integrations are enabled. If None, no infrastructure automation is enabled. Allowed values are \"AWS\", \"Azure\", \"BareMetal\", \"GCP\", \"Libvirt\", \"OpenStack\", \"VSphere\", \"oVirt\", and \"None\". Individual components may not support all platforms, and must handle unrecognized platforms as None if they do not support that platform.", @@ -830,6 +788,7 @@ var map_PlatformStatus = map[string]string{ "gcp": "GCP contains settings specific to the Google Cloud Platform infrastructure provider.", "baremetal": "BareMetal contains settings specific to the BareMetal platform.", "openstack": "OpenStack contains settings specific to the OpenStack infrastructure provider.", + "ovirt": "Ovirt contains settings specific to the oVirt infrastructure provider.", } func (PlatformStatus) SwaggerDoc() map[string]string { @@ -837,24 +796,15 @@ func (PlatformStatus) SwaggerDoc() map[string]string { } var map_Ingress = map[string]string{ - "": "Ingress holds cluster-wide information about ingress, including the default ingress domain used for routes. The canonical name is `cluster`.", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Ingress holds cluster-wide information about ingress, including the default ingress domain used for routes. The canonical name is `cluster`.", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Ingress) SwaggerDoc() map[string]string { return map_Ingress } -var map_IngressList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (IngressList) SwaggerDoc() map[string]string { - return map_IngressList -} - var map_IngressSpec = map[string]string{ "domain": "domain is used to generate a default host name for a route when the route's host name is empty. The generated host name will follow this pattern: \"..\".\n\nIt is also used as the default wildcard domain suffix for ingress. The default ingresscontroller domain will follow this pattern: \"*.\".\n\nOnce set, changing domain is not currently supported.", } @@ -894,24 +844,15 @@ func (ExternalIPPolicy) SwaggerDoc() map[string]string { } var map_Network = map[string]string{ - "": "Network holds cluster-wide information about Network. The canonical name is `cluster`. It is used to configure the desired network configuration, such as: IP address pools for services/pod IPs, network plugin, etc. Please view network.spec for an explanation on what applies when configuring this resource.", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration. As a general rule, this SHOULD NOT be read directly. Instead, you should consume the NetworkStatus, as it indicates the currently deployed configuration. Currently, most spec fields are immutable after installation. Please view the individual ones for further details on each.", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Network holds cluster-wide information about Network. The canonical name is `cluster`. It is used to configure the desired network configuration, such as: IP address pools for services/pod IPs, network plugin, etc. Please view network.spec for an explanation on what applies when configuring this resource.", + "spec": "spec holds user settable values for configuration. As a general rule, this SHOULD NOT be read directly. Instead, you should consume the NetworkStatus, as it indicates the currently deployed configuration. Currently, most spec fields are immutable after installation. Please view the individual ones for further details on each.", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Network) SwaggerDoc() map[string]string { return map_Network } -var map_NetworkList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (NetworkList) SwaggerDoc() map[string]string { - return map_NetworkList -} - var map_NetworkSpec = map[string]string{ "": "NetworkSpec is the desired network configuration. As a general rule, this SHOULD NOT be read directly. Instead, you should consume the NetworkStatus, as it indicates the currently deployed configuration. Currently, most spec fields are immutable after installation. Please view the individual ones for further details on each.", "clusterNetwork": "IP address pool to use for pod IPs. This field is immutable after installation.", @@ -1211,24 +1152,15 @@ func (OperatorHubStatus) SwaggerDoc() map[string]string { } var map_Project = map[string]string{ - "": "Project holds cluster-wide information about Project. The canonical name is `cluster`", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Project holds cluster-wide information about Project. The canonical name is `cluster`", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Project) SwaggerDoc() map[string]string { return map_Project } -var map_ProjectList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (ProjectList) SwaggerDoc() map[string]string { - return map_ProjectList -} - var map_ProjectSpec = map[string]string{ "": "ProjectSpec holds the project creation configuration.", "projectRequestMessage": "projectRequestMessage is the string presented to a user if they are unable to request a project via the projectrequest api endpoint", @@ -1258,14 +1190,6 @@ func (Proxy) SwaggerDoc() map[string]string { return map_Proxy } -var map_ProxyList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (ProxyList) SwaggerDoc() map[string]string { - return map_ProxyList -} - var map_ProxySpec = map[string]string{ "": "ProxySpec contains cluster proxy creation configuration.", "httpProxy": "httpProxy is the URL of the proxy for HTTP requests. Empty means unset and will not result in an env var.", @@ -1291,24 +1215,15 @@ func (ProxyStatus) SwaggerDoc() map[string]string { } var map_Scheduler = map[string]string{ - "": "Scheduler holds cluster-wide config information to run the Kubernetes Scheduler and influence its placement decisions. The canonical name for this config is `cluster`.", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", - "status": "status holds observed values from the cluster. They may not be overridden.", + "": "Scheduler holds cluster-wide config information to run the Kubernetes Scheduler and influence its placement decisions. The canonical name for this config is `cluster`.", + "spec": "spec holds user settable values for configuration", + "status": "status holds observed values from the cluster. They may not be overridden.", } func (Scheduler) SwaggerDoc() map[string]string { return map_Scheduler } -var map_SchedulerList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (SchedulerList) SwaggerDoc() map[string]string { - return map_SchedulerList -} - var map_SchedulerSpec = map[string]string{ "policy": "policy is a reference to a ConfigMap containing scheduler policy which has user specified predicates and priorities. If this ConfigMap is not available scheduler will default to use DefaultAlgorithmProvider. The namespace for this configmap is openshift-config.", "defaultNodeSelector": "defaultNodeSelector helps set the cluster-wide default node selector to restrict pod placement to specific nodes. This is applied to the pods created in all namespaces without a specified nodeSelector value. For example, defaultNodeSelector: \"type=user-node,region=east\" would set nodeSelector field in pod spec to \"type=user-node,region=east\" to all pods created in all namespaces. Namespaces having project-wide node selectors won't be impacted even if this field is set. This adds an annotation section to the namespace. For example, if a new namespace is created with node-selector='type=user-node,region=east', the annotation openshift.io/node-selector: type=user-node,region=east gets added to the project. When the openshift.io/node-selector annotation is set on the project the value is used in preference to the value we are setting for defaultNodeSelector field. For instance, openshift.io/node-selector: \"type=user-node,region=west\" means that the default of \"type=user-node,region=east\" set in defaultNodeSelector would not be applied.", @@ -1319,4 +1234,59 @@ func (SchedulerSpec) SwaggerDoc() map[string]string { return map_SchedulerSpec } +var map_CustomTLSProfile = map[string]string{ + "": "CustomTLSProfile is a user-defined TLS security profile. Be extremely careful using a custom TLS profile as invalid configurations can be catastrophic.", +} + +func (CustomTLSProfile) SwaggerDoc() map[string]string { + return map_CustomTLSProfile +} + +var map_IntermediateTLSProfile = map[string]string{ + "": "IntermediateTLSProfile is a TLS security profile based on: https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29", +} + +func (IntermediateTLSProfile) SwaggerDoc() map[string]string { + return map_IntermediateTLSProfile +} + +var map_ModernTLSProfile = map[string]string{ + "": "ModernTLSProfile is a TLS security profile based on: https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility", +} + +func (ModernTLSProfile) SwaggerDoc() map[string]string { + return map_ModernTLSProfile +} + +var map_OldTLSProfile = map[string]string{ + "": "OldTLSProfile is a TLS security profile based on: https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility", +} + +func (OldTLSProfile) SwaggerDoc() map[string]string { + return map_OldTLSProfile +} + +var map_TLSProfileSpec = map[string]string{ + "": "TLSProfileSpec is the desired behavior of a TLSSecurityProfile.", + "ciphers": "ciphers is used to specify the cipher algorithms that are negotiated during the TLS handshake. Operators may remove entries their operands do not support. For example, to use DES-CBC3-SHA (yaml):\n\n ciphers:\n - DES-CBC3-SHA", + "minTLSVersion": "minTLSVersion is used to specify the minimal version of the TLS protocol that is negotiated during the TLS handshake. For example, to use TLS versions 1.1, 1.2 and 1.3 (yaml):\n\n minTLSVersion: TLSv1.1", +} + +func (TLSProfileSpec) SwaggerDoc() map[string]string { + return map_TLSProfileSpec +} + +var map_TLSSecurityProfile = map[string]string{ + "": "TLSSecurityProfile defines the schema for a TLS security profile. This object is used by operators to apply TLS security settings to operands.", + "type": "type is one of Old, Intermediate, Modern or Custom. Custom provides the ability to specify individual TLS security profile parameters. Old, Intermediate and Modern are TLS security profiles based on:\n\nhttps://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations\n\nThe profiles are intent based, so they may change over time as new ciphers are developed and existing ciphers are found to be insecure. Depending on precisely which ciphers are available to a process, the list may be reduced.", + "old": "old is a TLS security profile based on:\n\nhttps://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility\n\nand looks like this (yaml):\n\n ciphers:\n - TLS_AES_128_GCM_SHA256\n - TLS_AES_256_GCM_SHA384\n - TLS_CHACHA20_POLY1305_SHA256\n - ECDHE-ECDSA-AES128-GCM-SHA256\n - ECDHE-RSA-AES128-GCM-SHA256\n - ECDHE-ECDSA-AES256-GCM-SHA384\n - ECDHE-RSA-AES256-GCM-SHA384\n - ECDHE-ECDSA-CHACHA20-POLY1305\n - ECDHE-RSA-CHACHA20-POLY1305\n - ECDHE-ECDSA-AES128-SHA256\n - ECDHE-RSA-AES128-SHA256\n - ECDHE-ECDSA-AES128-SHA\n - ECDHE-RSA-AES128-SHA\n - ECDHE-ECDSA-AES256-SHA\n - ECDHE-RSA-AES256-SHA\n - AES128-GCM-SHA256\n - AES256-GCM-SHA384\n - AES128-SHA256\n - AES128-SHA\n - AES256-SHA\n - DES-CBC3-SHA\n minTLSVersion: TLSv1.0", + "intermediate": "intermediate is a TLS security profile based on:\n\nhttps://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28recommended.29\n\nand looks like this (yaml):\n\n ciphers:\n - TLS_AES_128_GCM_SHA256\n - TLS_AES_256_GCM_SHA384\n - TLS_CHACHA20_POLY1305_SHA256\n - ECDHE-ECDSA-AES128-GCM-SHA256\n - ECDHE-RSA-AES128-GCM-SHA256\n - ECDHE-ECDSA-AES256-GCM-SHA384\n - ECDHE-RSA-AES256-GCM-SHA384\n - ECDHE-ECDSA-CHACHA20-POLY1305\n - ECDHE-RSA-CHACHA20-POLY1305\n minTLSVersion: TLSv1.2", + "modern": "modern is a TLS security profile based on:\n\nhttps://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility\n\nand looks like this (yaml):\n\n ciphers:\n - TLS_AES_128_GCM_SHA256\n - TLS_AES_256_GCM_SHA384\n - TLS_CHACHA20_POLY1305_SHA256\n minTLSVersion: TLSv1.3", + "custom": "custom is a user-defined TLS security profile. Be extremely careful using a custom profile as invalid configurations can be catastrophic. An example custom profile looks like this:\n\n ciphers:\n - ECDHE-ECDSA-CHACHA20-POLY1305\n - ECDHE-RSA-CHACHA20-POLY1305\n - ECDHE-RSA-AES128-GCM-SHA256\n - ECDHE-ECDSA-AES128-GCM-SHA256\n minTLSVersion: TLSv1.1", +} + +func (TLSSecurityProfile) SwaggerDoc() map[string]string { + return map_TLSSecurityProfile +} + // AUTO-GENERATED FUNCTIONS END HERE diff --git a/manifests/00-crd-consoleclidownloads.yaml b/vendor/github.com/openshift/api/console/v1/0000_10_consoleclidownload.crd.yaml similarity index 82% rename from manifests/00-crd-consoleclidownloads.yaml rename to vendor/github.com/openshift/api/console/v1/0000_10_consoleclidownload.crd.yaml index bf87ada81d..91fdd8e9ff 100644 --- a/manifests/00-crd-consoleclidownloads.yaml +++ b/vendor/github.com/openshift/api/console/v1/0000_10_consoleclidownload.crd.yaml @@ -8,35 +8,36 @@ metadata: (CLI) downloads. spec: scope: Cluster + preserveUnknownField: false group: console.openshift.io versions: - - name: v1 - served: true - storage: true + - name: v1 + served: true + storage: true names: plural: consoleclidownloads singular: consoleclidownload kind: ConsoleCLIDownload listKind: ConsoleCLIDownloadList additionalPrinterColumns: - - name: Display name - type: string - JSONPath: .spec.displayName - - name: Age - type: string - JSONPath: .metadata.creationTimestamp - - name: Description - type: string - JSONPath: .spec.description + - name: Display name + type: string + JSONPath: .spec.displayName + - name: Age + type: string + JSONPath: .metadata.creationTimestamp + - name: Description + type: string + JSONPath: .spec.description subresources: status: {} - validation: - openAPIV3Schema: + "validation": + "openAPIV3Schema": description: ConsoleCLIDownload is an extension for configuring openshift web console command line interface (CLI) downloads. type: object required: - - spec + - spec properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -49,15 +50,14 @@ spec: 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: - description: Standard object's metadata. type: object spec: description: ConsoleCLIDownloadSpec is the desired cli download configuration. type: object required: - - description - - displayName - - links + - description + - displayName + - links properties: description: description: description is the description of the CLI download (can @@ -73,13 +73,13 @@ spec: items: type: object required: - - href + - href properties: href: description: href is the absolute secure URL for the link (must use https) type: string - pattern: ^https://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$ + pattern: ^https:// text: description: text is the display text for the link type: string diff --git a/manifests/00-crd-consoleexternalloglinks.yaml b/vendor/github.com/openshift/api/console/v1/0000_10_consoleexternalloglink.crd.yaml similarity index 70% rename from manifests/00-crd-consoleexternalloglinks.yaml rename to vendor/github.com/openshift/api/console/v1/0000_10_consoleexternalloglink.crd.yaml index 67d30a7b69..0437cfddc1 100644 --- a/manifests/00-crd-consoleexternalloglinks.yaml +++ b/vendor/github.com/openshift/api/console/v1/0000_10_consoleexternalloglink.crd.yaml @@ -8,35 +8,36 @@ metadata: web console log links. spec: scope: Cluster + preserveUnknownField: false group: console.openshift.io versions: - - name: v1 - served: true - storage: true + - name: v1 + served: true + storage: true names: plural: consoleexternalloglinks singular: consoleexternalloglink kind: ConsoleExternalLogLink listKind: ConsoleExternalLogLinkList additionalPrinterColumns: - - name: Text - type: string - JSONPath: .spec.text - - name: HrefTemplate - type: string - JSONPath: .spec.hrefTemplate - - name: Age - type: date - JSONPath: .metadata.creationTimestamp + - name: Text + type: string + JSONPath: .spec.text + - name: HrefTemplate + type: string + JSONPath: .spec.hrefTemplate + - name: Age + type: date + JSONPath: .metadata.creationTimestamp subresources: status: {} - validation: - openAPIV3Schema: + "validation": + "openAPIV3Schema": description: ConsoleExternalLogLink is an extension for customizing OpenShift web console log links. type: object required: - - spec + - spec properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -49,31 +50,29 @@ spec: 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: - description: Standard object's metadata. type: object spec: description: ConsoleExternalLogLinkSpec is the desired log link configuration. The log link will appear on the logs tab of the pod details page. type: object required: - - hrefTemplate - - text + - hrefTemplate + - text properties: hrefTemplate: description: "hrefTemplate is an absolute secure URL (must use https) for the log link including variables to be replaced. Variables are specified in the URL with the format ${variableName}, for instance, ${containerName} and will be replaced with the corresponding values - from the resource. Resource is a pod. Supported variables are: - - ${resourceName} - name of the resource which containes the logs - - ${resourceUID} - UID of the resource which contains the logs - - e.g. `11111111-2222-3333-4444-555555555555` - - ${containerName} - name of the resource's container that contains the logs - - ${resourceNamespace} - namespace of the resource that contains the logs - - ${resourceNamespaceUID} - namespace UID of the resource that contains the logs - - ${podLabels} - JSON representation of labels matching the pod with the logs - - e.g. `{\"key1\":\"value1\",\"key2\":\"value2\"}` - e.g., https://example.com/logs?resourceName=${resourceName}&containerName=${containerName}&resourceNamespace=${resourceNamespace}&podLabels=${podLabels}" + from the resource. Resource is a pod. Supported variables are: - ${resourceName} + - name of the resource which containes the logs - ${resourceUID} - + UID of the resource which contains the logs - e.g. `11111111-2222-3333-4444-555555555555` + - ${containerName} - name of the resource's container that contains + the logs - ${resourceNamespace} - namespace of the resource that contains + the logs - ${resourceNamespaceUID} - namespace UID of the resource + that contains the logs - ${podLabels} - JSON representation of labels + matching the pod with the logs - e.g. `{\"key1\":\"value1\",\"key2\":\"value2\"}` + \n e.g., https://example.com/logs?resourceName=${resourceName}&containerName=${containerName}&resourceNamespace=${resourceNamespace}&podLabels=${podLabels}" type: string pattern: ^https:// namespaceFilter: @@ -86,4 +85,3 @@ spec: text: description: text is the display text for the link type: string - diff --git a/manifests/00-crd-consolelinks.yaml b/vendor/github.com/openshift/api/console/v1/0000_10_consolelink.crd.yaml similarity index 86% rename from manifests/00-crd-consolelinks.yaml rename to vendor/github.com/openshift/api/console/v1/0000_10_consolelink.crd.yaml index 9071f4a726..f68c2f9fd8 100644 --- a/manifests/00-crd-consolelinks.yaml +++ b/vendor/github.com/openshift/api/console/v1/0000_10_consolelink.crd.yaml @@ -7,38 +7,39 @@ metadata: description: Extension for customizing OpenShift web console links spec: scope: Cluster + preserveUnknownField: false group: console.openshift.io versions: - - name: v1 - served: true - storage: true + - name: v1 + served: true + storage: true names: plural: consolelinks singular: consolelink kind: ConsoleLink listKind: ConsoleLinkList additionalPrinterColumns: - - name: Text - type: string - JSONPath: .spec.text - - name: URL - type: string - JSONPath: .spec.href - - name: Menu - type: string - JSONPath: .spec.menu - - name: Age - type: date - JSONPath: .metadata.creationTimestamp + - name: Text + type: string + JSONPath: .spec.text + - name: URL + type: string + JSONPath: .spec.href + - name: Menu + type: string + JSONPath: .spec.menu + - name: Age + type: date + JSONPath: .metadata.creationTimestamp subresources: status: {} - validation: - openAPIV3Schema: + "validation": + "openAPIV3Schema": description: ConsoleLink is an extension for customizing OpenShift web console links. type: object required: - - spec + - spec properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -51,15 +52,14 @@ spec: 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: - description: Standard object's metadata. type: object spec: description: ConsoleLinkSpec is the desired console link configuration. type: object required: - - href - - location - - text + - href + - location + - text properties: applicationMenu: description: applicationMenu holds information about section and icon @@ -67,7 +67,7 @@ spec: when location is set to ApplicationMenu. type: object required: - - section + - section properties: imageURL: description: imageUrl is the URL for the icon used in front of the @@ -86,7 +86,7 @@ spec: description: href is the absolute secure URL for the link (must use https) type: string - pattern: ^https://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$ + pattern: ^https:// location: description: location determines which location in the console the link will be appended to (ApplicationMenu, HelpMenu, UserMenu, NamespaceDashboard). @@ -99,7 +99,7 @@ spec: link will appear in all namespaces. type: object required: - - namespaces + - namespaces properties: namespaces: description: namespaces is an array of namespace names in which diff --git a/manifests/00-crd-consolenotifications.yaml b/vendor/github.com/openshift/api/console/v1/0000_10_consolenotification.crd.yaml similarity index 84% rename from manifests/00-crd-consolenotifications.yaml rename to vendor/github.com/openshift/api/console/v1/0000_10_consolenotification.crd.yaml index 56f820c248..e487b3f0b7 100644 --- a/manifests/00-crd-consolenotifications.yaml +++ b/vendor/github.com/openshift/api/console/v1/0000_10_consolenotification.crd.yaml @@ -7,35 +7,36 @@ metadata: description: Extension for configuring openshift web console notifications. spec: scope: Cluster + preserveUnknownField: false group: console.openshift.io versions: - - name: v1 - served: true - storage: true + - name: v1 + served: true + storage: true names: plural: consolenotifications singular: consolenotification kind: ConsoleNotification listKind: ConsoleNotificationList additionalPrinterColumns: - - name: Text - type: string - JSONPath: .spec.text - - name: Location - type: string - JSONPath: .spec.location - - name: Age - type: date - JSONPath: .metadata.creationTimestamp + - name: Text + type: string + JSONPath: .spec.text + - name: Location + type: string + JSONPath: .spec.location + - name: Age + type: date + JSONPath: .metadata.creationTimestamp subresources: status: {} - validation: - openAPIV3Schema: + "validation": + "openAPIV3Schema": description: ConsoleNotification is the extension for configuring openshift web console notifications. type: object required: - - spec + - spec properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -48,14 +49,13 @@ spec: 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: - description: Standard object's metadata. type: object spec: description: ConsoleNotificationSpec is the desired console notification configuration. type: object required: - - text + - text properties: backgroundColor: description: backgroundColor is the color of the background for the @@ -69,14 +69,14 @@ spec: description: link is an object that holds notification link details. type: object required: - - href - - text + - href + - text properties: href: description: href is the absolute secure URL for the link (must use https) type: string - pattern: ^https://([\w-]+.)+[\w-]+(/[\w- ./?%&=])?$ + pattern: ^https:// text: description: text is the display text for the link type: string diff --git a/manifests/00-crd-consoleyamlsamples.yaml b/vendor/github.com/openshift/api/console/v1/0000_10_consoleyamlsample.crd.yaml similarity index 85% rename from manifests/00-crd-consoleyamlsamples.yaml rename to vendor/github.com/openshift/api/console/v1/0000_10_consoleyamlsample.crd.yaml index 07adae0c12..bd283a39d8 100644 --- a/manifests/00-crd-consoleyamlsamples.yaml +++ b/vendor/github.com/openshift/api/console/v1/0000_10_consoleyamlsample.crd.yaml @@ -9,34 +9,22 @@ spec: scope: Cluster group: console.openshift.io versions: - - name: v1 - served: true - storage: true + - name: v1 + served: true + storage: true names: plural: consoleyamlsamples singular: consoleyamlsample kind: ConsoleYAMLSample listKind: ConsoleYAMLSampleList - additionalPrinterColumns: - - name: Title - type: string - JSONPath: .spec.title - - name: Age - type: string - JSONPath: .metadata.creationTimestamp - - name: Description - type: string - JSONPath: .spec.description - subresources: - status: {} - validation: - openAPIV3Schema: + "validation": + "openAPIV3Schema": description: ConsoleYAMLSample is an extension for customizing OpenShift web console YAML samples. type: object required: - - metadata - - spec + - metadata + - spec properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -49,7 +37,6 @@ spec: 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: - description: Standard object's metadata. type: object spec: description: ConsoleYAMLSampleSpec is the desired YAML sample configuration. @@ -57,9 +44,9 @@ spec: creating a resources in the web console. type: object required: - - description - - title - - yaml + - description + - title + - yaml properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation diff --git a/vendor/github.com/openshift/api/console/v1/register.go b/vendor/github.com/openshift/api/console/v1/register.go index 98363daa3e..87e0c8ed76 100644 --- a/vendor/github.com/openshift/api/console/v1/register.go +++ b/vendor/github.com/openshift/api/console/v1/register.go @@ -39,6 +39,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &ConsoleNotificationList{}, &ConsoleExternalLogLink{}, &ConsoleExternalLogLinkList{}, + &ConsoleYAMLSample{}, + &ConsoleYAMLSampleList{}, ) metav1.AddToGroupVersion(scheme, GroupVersion) return nil diff --git a/vendor/github.com/openshift/api/console/v1/types.go b/vendor/github.com/openshift/api/console/v1/types.go index 3dea7005ab..416eaa3e87 100644 --- a/vendor/github.com/openshift/api/console/v1/types.go +++ b/vendor/github.com/openshift/api/console/v1/types.go @@ -5,5 +5,6 @@ type Link struct { // text is the display text for the link Text string `json:"text"` // href is the absolute secure URL for the link (must use https) + // +kubebuilder:validation:Pattern=`^https://` Href string `json:"href"` } diff --git a/vendor/github.com/openshift/api/console/v1/types_console_cli_download.go b/vendor/github.com/openshift/api/console/v1/types_console_cli_download.go index 00844a03c6..76ce0da7c1 100644 --- a/vendor/github.com/openshift/api/console/v1/types_console_cli_download.go +++ b/vendor/github.com/openshift/api/console/v1/types_console_cli_download.go @@ -8,10 +8,10 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // ConsoleCLIDownload is an extension for configuring openshift web console command line interface (CLI) downloads. type ConsoleCLIDownload struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ConsoleCLIDownloadSpec `json:"spec"` + + Spec ConsoleCLIDownloadSpec `json:"spec"` } // ConsoleCLIDownloadSpec is the desired cli download configuration. @@ -21,14 +21,23 @@ type ConsoleCLIDownloadSpec struct { // description is the description of the CLI download (can include markdown). Description string `json:"description"` // links is a list of objects that provide CLI download link details. - Links []Link `json:"links"` + Links []CLIDownloadLink `json:"links"` +} + +type CLIDownloadLink struct { + // text is the display text for the link + // +optional + Text string `json:"text"` + // href is the absolute secure URL for the link (must use https) + // +kubebuilder:validation:Pattern=`^https://` + Href string `json:"href"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object type ConsoleCLIDownloadList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []ConsoleCLIDownload `json:"items"` + + Items []ConsoleCLIDownload `json:"items"` } diff --git a/vendor/github.com/openshift/api/console/v1/types_console_external_log_links.go b/vendor/github.com/openshift/api/console/v1/types_console_external_log_links.go index c9c3317d51..2e77155129 100644 --- a/vendor/github.com/openshift/api/console/v1/types_console_external_log_links.go +++ b/vendor/github.com/openshift/api/console/v1/types_console_external_log_links.go @@ -8,10 +8,10 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // ConsoleExternalLogLink is an extension for customizing OpenShift web console log links. type ConsoleExternalLogLink struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ConsoleExternalLogLinkSpec `json:"spec"` + + Spec ConsoleExternalLogLinkSpec `json:"spec"` } // ConsoleExternalLogLinkSpec is the desired log link configuration. @@ -29,16 +29,18 @@ type ConsoleExternalLogLinkSpec struct { // - e.g. `11111111-2222-3333-4444-555555555555` // - ${containerName} - name of the resource's container that contains the logs // - ${resourceNamespace} - namespace of the resource that contains the logs + // - ${resourceNamespaceUID} - namespace UID of the resource that contains the logs // - ${podLabels} - JSON representation of labels matching the pod with the logs // - e.g. `{"key1":"value1","key2":"value2"}` // // e.g., https://example.com/logs?resourceName=${resourceName}&containerName=${containerName}&resourceNamespace=${resourceNamespace}&podLabels=${podLabels} + // +kubebuilder:validation:Pattern=`^https://` HrefTemplate string `json:"hrefTemplate"` // namespaceFilter is a regular expression used to restrict a log link to a // matching set of namespaces (e.g., `^openshift-`). The string is converted // into a regular expression using the JavaScript RegExp constructor. // If not specified, links will be displayed for all the namespaces. - // + optional + // +optional NamespaceFilter string `json:"namespaceFilter,omitempty"` } @@ -46,7 +48,7 @@ type ConsoleExternalLogLinkSpec struct { type ConsoleExternalLogLinkList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []ConsoleExternalLogLink `json:"items"` + + Items []ConsoleExternalLogLink `json:"items"` } diff --git a/vendor/github.com/openshift/api/console/v1/types_console_link.go b/vendor/github.com/openshift/api/console/v1/types_console_link.go index 9b7c4ba305..297fd36bff 100644 --- a/vendor/github.com/openshift/api/console/v1/types_console_link.go +++ b/vendor/github.com/openshift/api/console/v1/types_console_link.go @@ -8,16 +8,16 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // ConsoleLink is an extension for customizing OpenShift web console links. type ConsoleLink struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ConsoleLinkSpec `json:"spec"` + + Spec ConsoleLinkSpec `json:"spec"` } // ConsoleLinkSpec is the desired console link configuration. type ConsoleLinkSpec struct { Link `json:",inline"` - // location determines which location in the console the link will be appended to. + // location determines which location in the console the link will be appended to (ApplicationMenu, HelpMenu, UserMenu, NamespaceDashboard). Location ConsoleLinkLocation `json:"location"` // applicationMenu holds information about section and icon used for the link in the // application menu, and it is applicable only when location is set to ApplicationMenu. @@ -35,6 +35,8 @@ type ConsoleLinkSpec struct { // ApplicationMenuSpec is the specification of the desired section and icon used for the link in the application menu. type ApplicationMenuSpec struct { // section is the section of the application menu in which the link should appear. + // This can be any text that will appear as a subheading in the application menu dropdown. + // A new section will be created if the text does not match text of an existing section. Section string `json:"section"` // imageUrl is the URL for the icon used in front of the link in the application menu. // The URL must be an HTTPS URL or a Data URI. The image should be square and will be shown at 24x24 pixels. @@ -49,6 +51,7 @@ type NamespaceDashboardSpec struct { } // ConsoleLinkLocationSelector is a set of possible menu targets to which a link may be appended. +// +kubebuilder:validation:Pattern=`^(ApplicationMenu|HelpMenu|UserMenu|NamespaceDashboard)$` type ConsoleLinkLocation string const ( @@ -66,7 +69,7 @@ const ( type ConsoleLinkList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []ConsoleLink `json:"items"` + + Items []ConsoleLink `json:"items"` } diff --git a/vendor/github.com/openshift/api/console/v1/types_console_notification.go b/vendor/github.com/openshift/api/console/v1/types_console_notification.go index b4347fe3a3..86b1cd86e8 100644 --- a/vendor/github.com/openshift/api/console/v1/types_console_notification.go +++ b/vendor/github.com/openshift/api/console/v1/types_console_notification.go @@ -8,10 +8,10 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // ConsoleNotification is the extension for configuring openshift web console notifications. type ConsoleNotification struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec ConsoleNotificationSpec `json:"spec"` + + Spec ConsoleNotificationSpec `json:"spec"` } // ConsoleNotificationSpec is the desired console notification configuration. @@ -34,6 +34,7 @@ type ConsoleNotificationSpec struct { // ConsoleNotificationLocationSelector is a set of possible notification targets // to which a notification may be appended. +// +kubebuilder:validation:Pattern=`^(BannerTop|BannerBottom|BannerTopBottom)$` type ConsoleNotificationLocation string const ( @@ -49,7 +50,7 @@ const ( type ConsoleNotificationList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []ConsoleNotification `json:"items"` + + Items []ConsoleNotification `json:"items"` } diff --git a/vendor/github.com/openshift/api/console/v1/types_console_yaml_sample.go b/vendor/github.com/openshift/api/console/v1/types_console_yaml_sample.go new file mode 100644 index 0000000000..0d4091f737 --- /dev/null +++ b/vendor/github.com/openshift/api/console/v1/types_console_yaml_sample.go @@ -0,0 +1,51 @@ +package v1 + +import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ConsoleYAMLSample is an extension for customizing OpenShift web console YAML samples. +type ConsoleYAMLSample struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + Spec ConsoleYAMLSampleSpec `json:"spec"` +} + +// ConsoleYAMLSampleSpec is the desired YAML sample configuration. +// Samples will appear with their descriptions in a samples sidebar +// when creating a resources in the web console. +type ConsoleYAMLSampleSpec struct { + // targetResource contains apiVersion and kind of the resource + // YAML sample is representating. + TargetResource metav1.TypeMeta `json:",targetResource"` + // title of the YAML sample. + Title ConsoleYAMLSampleTitle `json:"title"` + // description of the YAML sample. + Description ConsoleYAMLSampleDescription `json:"description"` + // yaml is the YAML sample to display. + YAML ConsoleYAMLSampleYAML `json:"yaml"` +} + +// ConsoleYAMLSampleTitle of the YAML sample. +// +kubebuilder:validation:Pattern=`^(.|\s)*\S(.|\s)*$` +type ConsoleYAMLSampleTitle string + +// ConsoleYAMLSampleDescription of the YAML sample. +// +kubebuilder:validation:Pattern=`^(.|\s)*\S(.|\s)*$` +type ConsoleYAMLSampleDescription string + +// ConsoleYAMLSampleYAML is the YAML sample to display. +// +kubebuilder:validation:Pattern=`^(.|\s)*\S(.|\s)*$` +type ConsoleYAMLSampleYAML string + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type ConsoleYAMLSampleList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []ConsoleYAMLSample `json:"items"` +} diff --git a/vendor/github.com/openshift/api/console/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/console/v1/zz_generated.deepcopy.go index 9c32f2d822..d1231420bf 100644 --- a/vendor/github.com/openshift/api/console/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/console/v1/zz_generated.deepcopy.go @@ -24,6 +24,22 @@ func (in *ApplicationMenuSpec) DeepCopy() *ApplicationMenuSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CLIDownloadLink) DeepCopyInto(out *CLIDownloadLink) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CLIDownloadLink. +func (in *CLIDownloadLink) DeepCopy() *CLIDownloadLink { + if in == nil { + return nil + } + out := new(CLIDownloadLink) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ConsoleCLIDownload) DeepCopyInto(out *ConsoleCLIDownload) { *out = *in @@ -89,7 +105,7 @@ func (in *ConsoleCLIDownloadSpec) DeepCopyInto(out *ConsoleCLIDownloadSpec) { *out = *in if in.Links != nil { in, out := &in.Links, &out.Links - *out = make([]Link, len(*in)) + *out = make([]CLIDownloadLink, len(*in)) copy(*out, *in) } return @@ -349,6 +365,83 @@ func (in *ConsoleNotificationSpec) DeepCopy() *ConsoleNotificationSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConsoleYAMLSample) DeepCopyInto(out *ConsoleYAMLSample) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleYAMLSample. +func (in *ConsoleYAMLSample) DeepCopy() *ConsoleYAMLSample { + if in == nil { + return nil + } + out := new(ConsoleYAMLSample) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ConsoleYAMLSample) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConsoleYAMLSampleList) DeepCopyInto(out *ConsoleYAMLSampleList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ConsoleYAMLSample, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleYAMLSampleList. +func (in *ConsoleYAMLSampleList) DeepCopy() *ConsoleYAMLSampleList { + if in == nil { + return nil + } + out := new(ConsoleYAMLSampleList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ConsoleYAMLSampleList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConsoleYAMLSampleSpec) DeepCopyInto(out *ConsoleYAMLSampleSpec) { + *out = *in + out.TargetResource = in.TargetResource + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConsoleYAMLSampleSpec. +func (in *ConsoleYAMLSampleSpec) DeepCopy() *ConsoleYAMLSampleSpec { + if in == nil { + return nil + } + out := new(ConsoleYAMLSampleSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Link) DeepCopyInto(out *Link) { *out = *in diff --git a/vendor/github.com/openshift/api/console/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/console/v1/zz_generated.swagger_doc_generated.go index 5d9729ed0c..e953fcc902 100644 --- a/vendor/github.com/openshift/api/console/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/console/v1/zz_generated.swagger_doc_generated.go @@ -21,21 +21,21 @@ func (Link) SwaggerDoc() map[string]string { return map_Link } -var map_ConsoleCLIDownload = map[string]string{ - "": "ConsoleCLIDownload is an extension for configuring openshift web console command line interface (CLI) downloads.", - "metadata": "Standard object's metadata.", +var map_CLIDownloadLink = map[string]string{ + "text": "text is the display text for the link", + "href": "href is the absolute secure URL for the link (must use https)", } -func (ConsoleCLIDownload) SwaggerDoc() map[string]string { - return map_ConsoleCLIDownload +func (CLIDownloadLink) SwaggerDoc() map[string]string { + return map_CLIDownloadLink } -var map_ConsoleCLIDownloadList = map[string]string{ - "metadata": "Standard object's metadata.", +var map_ConsoleCLIDownload = map[string]string{ + "": "ConsoleCLIDownload is an extension for configuring openshift web console command line interface (CLI) downloads.", } -func (ConsoleCLIDownloadList) SwaggerDoc() map[string]string { - return map_ConsoleCLIDownloadList +func (ConsoleCLIDownload) SwaggerDoc() map[string]string { + return map_ConsoleCLIDownload } var map_ConsoleCLIDownloadSpec = map[string]string{ @@ -50,26 +50,17 @@ func (ConsoleCLIDownloadSpec) SwaggerDoc() map[string]string { } var map_ConsoleExternalLogLink = map[string]string{ - "": "ConsoleExternalLogLink is an extension for customizing OpenShift web console log links.", - "metadata": "Standard object's metadata.", + "": "ConsoleExternalLogLink is an extension for customizing OpenShift web console log links.", } func (ConsoleExternalLogLink) SwaggerDoc() map[string]string { return map_ConsoleExternalLogLink } -var map_ConsoleExternalLogLinkList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (ConsoleExternalLogLinkList) SwaggerDoc() map[string]string { - return map_ConsoleExternalLogLinkList -} - var map_ConsoleExternalLogLinkSpec = map[string]string{ "": "ConsoleExternalLogLinkSpec is the desired log link configuration. The log link will appear on the logs tab of the pod details page.", "text": "text is the display text for the link", - "hrefTemplate": "hrefTemplate is an absolute secure URL (must use https) for the log link including variables to be replaced. Variables are specified in the URL with the format ${variableName}, for instance, ${containerName} and will be replaced with the corresponding values from the resource. Resource is a pod. Supported variables are: - ${resourceName} - name of the resource which containes the logs - ${resourceUID} - UID of the resource which contains the logs\n - e.g. `11111111-2222-3333-4444-555555555555`\n- ${containerName} - name of the resource's container that contains the logs - ${resourceNamespace} - namespace of the resource that contains the logs - ${podLabels} - JSON representation of labels matching the pod with the logs\n - e.g. `{\"key1\":\"value1\",\"key2\":\"value2\"}`\n\ne.g., https://example.com/logs?resourceName=${resourceName}&containerName=${containerName}&resourceNamespace=${resourceNamespace}&podLabels=${podLabels}", + "hrefTemplate": "hrefTemplate is an absolute secure URL (must use https) for the log link including variables to be replaced. Variables are specified in the URL with the format ${variableName}, for instance, ${containerName} and will be replaced with the corresponding values from the resource. Resource is a pod. Supported variables are: - ${resourceName} - name of the resource which containes the logs - ${resourceUID} - UID of the resource which contains the logs\n - e.g. `11111111-2222-3333-4444-555555555555`\n- ${containerName} - name of the resource's container that contains the logs - ${resourceNamespace} - namespace of the resource that contains the logs - ${resourceNamespaceUID} - namespace UID of the resource that contains the logs - ${podLabels} - JSON representation of labels matching the pod with the logs\n - e.g. `{\"key1\":\"value1\",\"key2\":\"value2\"}`\n\ne.g., https://example.com/logs?resourceName=${resourceName}&containerName=${containerName}&resourceNamespace=${resourceNamespace}&podLabels=${podLabels}", "namespaceFilter": "namespaceFilter is a regular expression used to restrict a log link to a matching set of namespaces (e.g., `^openshift-`). The string is converted into a regular expression using the JavaScript RegExp constructor. If not specified, links will be displayed for all the namespaces.", } @@ -79,7 +70,7 @@ func (ConsoleExternalLogLinkSpec) SwaggerDoc() map[string]string { var map_ApplicationMenuSpec = map[string]string{ "": "ApplicationMenuSpec is the specification of the desired section and icon used for the link in the application menu.", - "section": "section is the section of the application menu in which the link should appear.", + "section": "section is the section of the application menu in which the link should appear. This can be any text that will appear as a subheading in the application menu dropdown. A new section will be created if the text does not match text of an existing section.", "imageURL": "imageUrl is the URL for the icon used in front of the link in the application menu. The URL must be an HTTPS URL or a Data URI. The image should be square and will be shown at 24x24 pixels.", } @@ -88,25 +79,16 @@ func (ApplicationMenuSpec) SwaggerDoc() map[string]string { } var map_ConsoleLink = map[string]string{ - "": "ConsoleLink is an extension for customizing OpenShift web console links.", - "metadata": "Standard object's metadata.", + "": "ConsoleLink is an extension for customizing OpenShift web console links.", } func (ConsoleLink) SwaggerDoc() map[string]string { return map_ConsoleLink } -var map_ConsoleLinkList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (ConsoleLinkList) SwaggerDoc() map[string]string { - return map_ConsoleLinkList -} - var map_ConsoleLinkSpec = map[string]string{ "": "ConsoleLinkSpec is the desired console link configuration.", - "location": "location determines which location in the console the link will be appended to.", + "location": "location determines which location in the console the link will be appended to (ApplicationMenu, HelpMenu, UserMenu, NamespaceDashboard).", "applicationMenu": "applicationMenu holds information about section and icon used for the link in the application menu, and it is applicable only when location is set to ApplicationMenu.", "namespaceDashboard": "namespaceDashboard holds information about namespaces in which the dashboard link should appear, and it is applicable only when location is set to NamespaceDashboard. If not specified, the link will appear in all namespaces.", } @@ -125,22 +107,13 @@ func (NamespaceDashboardSpec) SwaggerDoc() map[string]string { } var map_ConsoleNotification = map[string]string{ - "": "ConsoleNotification is the extension for configuring openshift web console notifications.", - "metadata": "Standard object's metadata.", + "": "ConsoleNotification is the extension for configuring openshift web console notifications.", } func (ConsoleNotification) SwaggerDoc() map[string]string { return map_ConsoleNotification } -var map_ConsoleNotificationList = map[string]string{ - "metadata": "Standard object's metadata.", -} - -func (ConsoleNotificationList) SwaggerDoc() map[string]string { - return map_ConsoleNotificationList -} - var map_ConsoleNotificationSpec = map[string]string{ "": "ConsoleNotificationSpec is the desired console notification configuration.", "text": "text is the visible text of the notification.", @@ -154,4 +127,24 @@ func (ConsoleNotificationSpec) SwaggerDoc() map[string]string { return map_ConsoleNotificationSpec } +var map_ConsoleYAMLSample = map[string]string{ + "": "ConsoleYAMLSample is an extension for customizing OpenShift web console YAML samples.", +} + +func (ConsoleYAMLSample) SwaggerDoc() map[string]string { + return map_ConsoleYAMLSample +} + +var map_ConsoleYAMLSampleSpec = map[string]string{ + "": "ConsoleYAMLSampleSpec is the desired YAML sample configuration. Samples will appear with their descriptions in a samples sidebar when creating a resources in the web console.", + "TargetResource": "targetResource contains apiVersion and kind of the resource YAML sample is representating.", + "title": "title of the YAML sample.", + "description": "description of the YAML sample.", + "yaml": "yaml is the YAML sample to display.", +} + +func (ConsoleYAMLSampleSpec) SwaggerDoc() map[string]string { + return map_ConsoleYAMLSampleSpec +} + // AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/Makefile b/vendor/github.com/openshift/api/hack/alpha-build-machinery/Makefile new file mode 100644 index 0000000000..b44d020e4b --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/Makefile @@ -0,0 +1,61 @@ +SHELL :=/bin/bash +all: verify +.PHONY: all + +makefiles :=$(wildcard ./make/*.example.mk) +examples :=$(wildcard ./make/examples/*/Makefile.test) + +# $1 - makefile name relative to ./make/ folder +# $2 - target +# $3 - output folder +# We need to change dir to the final makefile directory or relative paths won't match. +# Dynamic values are replaced with "" so we can do diff against checkout versions. +# Avoid comparing local paths by stripping the prefix. +# Delete lines referencing temporary files and directories +# Unify make error output between versions +# Ignore old cp errors on centos7 +# Ignore different make output with `-k` option +define update-makefile-log +mkdir -p "$(3)" +set -o pipefail; $(MAKE) -j 1 -C "$(dir $(1))" -f "$(notdir $(1))" --no-print-directory --warn-undefined-variables $(2) 2>&1 | \ + sed 's/\.\(buildDate\|versionFromGit\|commitFromGit\|gitTreeState\)="[^"]*" /.\1="" /g' | \ + sed -E 's~/.*/(github.com/openshift/library-go/alpha-build-machinery/.*)~/\1~g' | \ + sed '/\/tmp\/tmp./d' | \ + sed '/git checkout -b/d' | \ + sed -E 's~^[<> ]*((\+\+\+|\-\-\-) \./(testing/)?manifests/.*.yaml).*~\1~' | \ + sed -E 's/^(make\[2\]: \*\*\* \[).*: (.*\] Error 1)/\1\2/' | \ + grep -v 'are the same file' | \ + grep -E -v -e '^make\[2\]: Target `.*'"'"' not remade because of errors\.$$' | \ + tee "$(3)"/"$(notdir $(1))"$(subst ..,.,.$(2).log) + +endef + + +# $1 - makefile name relative to ./make/ folder +# $2 - target +# $3 - output folder +define check-makefile-log +$(call update-makefile-log,$(1),$(2),$(3)) +diff -N "$(1)$(subst ..,.,.$(2).log)" "$(3)/$(notdir $(1))$(subst ..,.,.$(2).log)" + +endef + +update-makefiles: + $(foreach f,$(makefiles),$(call check-makefile-log,$(f),help,$(dir $(f)))) + $(foreach f,$(examples),$(call check-makefile-log,$(f),,$(dir $(f)))) +.PHONY: update-makefiles + +verify-makefiles: tmp_dir:=$(shell mktemp -d) +verify-makefiles: + $(foreach f,$(makefiles),$(call check-makefile-log,$(f),help,$(tmp_dir)/$(dir $(f)))) + $(foreach f,$(examples),$(call check-makefile-log,$(f),,$(tmp_dir)/$(dir $(f)))) +.PHONY: verify-makefiles + +verify: verify-makefiles +.PHONY: verify + +update: update-makefiles +.PHONY: update + + +include ./make/targets/help.mk diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/OWNERS b/vendor/github.com/openshift/api/hack/alpha-build-machinery/OWNERS new file mode 100644 index 0000000000..ff2b6a24c8 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/OWNERS @@ -0,0 +1,4 @@ +reviewers: + - tnozicka +approvers: + - tnozicka diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/README.md b/vendor/github.com/openshift/api/hack/alpha-build-machinery/README.md new file mode 100644 index 0000000000..294a5834a8 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/README.md @@ -0,0 +1,37 @@ +# library-go/alpha-build-machinery +These are the building blocks for this and many of our other repositories to share code for Makefiles, helper scripts and other build related machinery. + +## Makefiles +`make/` directory contains several predefined makefiles `(*.mk)` to choose from and include one of them as a base in your final `Makefile`. These are the predefined flows providing you with e.g. `build`, `test` or `verify` targets. To start with it is recommended you base Makefile on the corresponding `*.example.mk` using copy&paste. + +As some advanced targets are generated, every Makefile contains `make help` target listing all the available ones. All of the "example" makefiles have a corresponding `.help` file listing all the targets available there. + +Also for advanced use and if none of the predefined flows doesn't fit your needs, you can compose the flow from modules in similar way to how the predefined flows do, + +### Golang +Standard makefile for building pure Golang projects. + - [make/golang.mk](make/golang.mk) + - [make/golang.example.mk](make/golang.example.mk) + - [make/golang.example.mk.help](make/golang.example.mk.help) + +### Default +Standard makefile for OpenShift Golang projects. + +Extends [#Golang](). + + - [make/default.mk](make/default.mk) + - [make/default.example.mk](make/default.example.mk) + - [make/default.example.mk.help](make/default.example.mk.help) + +### Operator +Standard makefile for OpenShift Golang projects. + +Extends [#Default](). + + - [make/operator.mk](make/operator.mk) + - [make/operator.example.mk](make/operator.example.mk) + - [make/operator.example.mk.help](make/operator.example.mk.help) + + +## Scripts +`scripts` contain more complicated logic that is used in some make targets. diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/doc.go new file mode 100644 index 0000000000..a093b4bd17 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/doc.go @@ -0,0 +1,14 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery + +// this is a dependency magnet to make it easier to pull in the build-machinery. We want a single import to pull all of it in. +import ( + _ "github.com/openshift/library-go/alpha-build-machinery/make" + _ "github.com/openshift/library-go/alpha-build-machinery/make/lib" + _ "github.com/openshift/library-go/alpha-build-machinery/make/targets" + _ "github.com/openshift/library-go/alpha-build-machinery/make/targets/golang" + _ "github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift" + _ "github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/operator" + _ "github.com/openshift/library-go/alpha-build-machinery/scripts" +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.example.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.example.mk new file mode 100644 index 0000000000..fffc5b3a3c --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.example.mk @@ -0,0 +1,40 @@ +all: build +.PHONY: all + +# You can customize go tools depending on the directory layout. +# example: +GO_BUILD_PACKAGES :=./pkg/... +# You can list all the golang related variables by: +# $ make -n --print-data-base | grep ^GO + +# Include the library makefile +include ./default.mk +# All the available targets are listed in .help +# or you can list it live by using `make help` + +# Codegen module needs setting these required variables +CODEGEN_OUTPUT_PACKAGE :=github.com/openshift/cluster-openshift-apiserver-operator/pkg/generated +CODEGEN_API_PACKAGE :=github.com/openshift/cluster-openshift-apiserver-operator/pkg/apis +CODEGEN_GROUPS_VERSION :=openshiftapiserver:v1alpha1 +# You can list all codegen related variables by: +# $ make -n --print-data-base | grep ^CODEGEN + +# This will call a macro called "build-image" which will generate image specific targets based on the parameters: +# $1 - target name +# $2 - image ref +# $3 - Dockerfile path +# $4 - context +# It will generate target "image-$(1)" for builing the image an binding it as a prerequisite to target "images". +$(call build-image,ocp-cli,registry.svc.ci.openshift.org/ocp/4.2:cli,./images/cli/Dockerfile.rhel,.) + +# This will call a macro called "add-bindata" which will generate bindata specific targets based on the parameters: +# $0 - macro name +# $1 - target suffix +# $2 - input dirs +# $3 - prefix +# $4 - pkg +# $5 - output +# It will generate targets {update,verify}-bindata-$(1) logically grouping them in unsuffixed versions of these targets +# and also hooked into {update,verify}-generated for broader integration. +$(call add-bindata,v3.11.0,./bindata/v3.11.0/...,bindata,v311_00_assets,pkg/operator/v311_00_assets/bindata.go) + diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.example.mk.help.log b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.example.mk.help.log new file mode 100644 index 0000000000..92aa6acdbb --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.example.mk.help.log @@ -0,0 +1,25 @@ +The following make targets are available: +all +build +clean +clean-binaries +help +image-ocp-cli +images +test +test-unit +update +update-bindata +update-codegen +update-deps +update-deps-overrides +update-generated +update-gofmt +verify +verify-bindata +verify-codegen +verify-deps +verify-generated +verify-gofmt +verify-golint +verify-govet diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.mk new file mode 100644 index 0000000000..564fc12297 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/default.mk @@ -0,0 +1,23 @@ +self_dir := $(dir $(lastword $(MAKEFILE_LIST))) + +# We extend the default verify/update for Golang + +verify: verify-codegen +verify: verify-bindata +.PHONY: verify + +update: update-codegen +update: update-bindata +.PHONY: update + + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + targets/openshift/deps.mk \ + targets/openshift/images.mk \ + targets/openshift/bindata.mk \ + targets/openshift/codegen.mk \ + golang.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/doc.go new file mode 100644 index 0000000000..66ba5512e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/doc.go @@ -0,0 +1,3 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.example.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.example.mk new file mode 100644 index 0000000000..aba2c48903 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.example.mk @@ -0,0 +1,14 @@ +all: build +.PHONY: all + + +# You can customize go tools depending on the directory layout. +# example: +GO_BUILD_PACKAGES :=./pkg/... +# You can list all the golang related variables by: +# $ make -n --print-data-base | grep ^GO + +# Include the library makefile +include ./golang.mk +# All the available targets are listed in .help +# or you can list it live by using `make help` diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.example.mk.help.log b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.example.mk.help.log new file mode 100644 index 0000000000..a5cc906ddf --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.example.mk.help.log @@ -0,0 +1,14 @@ +The following make targets are available: +all +build +clean +clean-binaries +help +test +test-unit +update +update-gofmt +verify +verify-gofmt +verify-golint +verify-govet diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.mk new file mode 100644 index 0000000000..15a0b49bcb --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/golang.mk @@ -0,0 +1,28 @@ +all: build +.PHONY: all + +self_dir := $(dir $(lastword $(MAKEFILE_LIST))) + + +verify: verify-gofmt +verify: verify-govet +.PHONY: verify + +update: update-gofmt +.PHONY: update + + +test: test-unit +.PHONY: test + +clean: clean-binaries +.PHONY: clean + + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. +include $(addprefix $(self_dir), \ + targets/help.mk \ + targets/golang/*.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/doc.go new file mode 100644 index 0000000000..66ba5512e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/doc.go @@ -0,0 +1,3 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/golang.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/golang.mk new file mode 100644 index 0000000000..89d457ef0e --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/golang.mk @@ -0,0 +1,39 @@ +GO ?=go +GOPATH ?=$(shell $(GO) env GOPATH) +GO_PACKAGE ?=$(shell $(GO) list -e -f '{{ .ImportPath }}' . || echo 'no_package_detected') + +GOOS ?=$(shell $(GO) env GOOS) +GOHOSTOS ?=$(shell $(GO) env GOHOSTOS) +GOARCH ?=$(shell $(GO) env GOARCH) +GOHOSTARCH ?=$(shell $(GO) env GOHOSTARCH) +GOEXE ?=$(shell $(GO) env GOEXE) + +GOFMT ?=gofmt +GOFMT_FLAGS ?=-s -l +GOLINT ?=golint + +GO_FILES ?=$(shell find . -name '*.go' -not -path '*/vendor/*' -not -path '*/_output/*' -print) +GO_PACKAGES ?=./... +GO_TEST_PACKAGES ?=$(GO_PACKAGES) + +GO_BUILD_PACKAGES ?=./cmd/... +GO_BUILD_PACKAGES_EXPANDED ?=$(shell $(GO) list $(GO_BUILD_PACKAGES)) +go_build_binaries =$(notdir $(GO_BUILD_PACKAGES_EXPANDED)) +GO_BUILD_FLAGS ?= +GO_BUILD_BINDIR ?= + +GO_TEST_FLAGS ?=-race + +GO_LD_EXTRAFLAGS ?= + +SOURCE_GIT_TAG ?=$(shell git describe --long --tags --abbrev=7 --match 'v[0-9]*' || echo 'v0.0.0-unknown') +SOURCE_GIT_COMMIT ?=$(shell git rev-parse --short "HEAD^{commit}" 2>/dev/null) +SOURCE_GIT_TREE_STATE ?=$(shell ( ( [ ! -d ".git/" ] || git diff --quiet ) && echo 'clean' ) || echo 'dirty') + +define version-ldflags +-X $(1).versionFromGit="$(SOURCE_GIT_TAG)" \ +-X $(1).commitFromGit="$(SOURCE_GIT_COMMIT)" \ +-X $(1).gitTreeState="$(SOURCE_GIT_TREE_STATE)" \ +-X $(1).buildDate="$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')" +endef +GO_LD_FLAGS ?=-ldflags "-s -w $(call version-ldflags,$(GO_PACKAGE)/pkg/version) $(GO_LD_EXTRAFLAGS)" diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/tmp.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/tmp.mk new file mode 100644 index 0000000000..a0fb655359 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/lib/tmp.mk @@ -0,0 +1,2 @@ +PERMANENT_TMP :=_output +PERMANENT_TMP_GOPATH :=$(PERMANENT_TMP)/tools diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.example.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.example.mk new file mode 100644 index 0000000000..7e6ff98d56 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.example.mk @@ -0,0 +1,42 @@ +all: build +.PHONY: all + + +# You can customize go tools depending on the directory layout. +# example: +GO_BUILD_PACKAGES :=./pkg/... +# You can list all the golang related variables by: +# $ make -n --print-data-base | grep ^GO + +# Include the library makefile +include ./operator.mk +# All the available targets are listed in .help +# or you can list it live by using `make help` + + +# Codegen module needs setting these required variables +CODEGEN_OUTPUT_PACKAGE :=github.com/openshift/cluster-openshift-apiserver-operator/pkg/generated +CODEGEN_API_PACKAGE :=github.com/openshift/cluster-openshift-apiserver-operator/pkg/apis +CODEGEN_GROUPS_VERSION :=openshiftapiserver:v1alpha1 +# You can list all codegen related variables by: +# $ make -n --print-data-base | grep ^CODEGEN + +# This will call a macro called "build-image" which will generate image specific targets based on the parameters: +# $1 - target name +# $2 - image ref +# $3 - Dockerfile path +# $4 - context +# It will generate target "image-$(1)" for builing the image an binding it as a prerequisite to target "images". +$(call build-image,ocp-openshift-apiserver-operator,registry.svc.ci.openshift.org/ocp/4.2:openshift-apiserver-operator,./Dockerfile.rhel,.) + +# This will call a macro called "add-bindata" which will generate bindata specific targets based on the parameters: +# $0 - macro name +# $1 - target suffix +# $2 - input dirs +# $3 - prefix +# $4 - pkg +# $5 - output +# It will generate targets {update,verify}-bindata-$(1) logically grouping them in unsuffixed versions of these targets +# and also hooked into {update,verify}-generated for broader integration. +$(call add-bindata,v3.11.0,./bindata/v3.11.0/...,bindata,v311_00_assets,pkg/operator/v311_00_assets/bindata.go) + diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.example.mk.help.log b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.example.mk.help.log new file mode 100644 index 0000000000..a1489d212b --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.example.mk.help.log @@ -0,0 +1,25 @@ +The following make targets are available: +all +build +clean +clean-binaries +help +image-ocp-openshift-apiserver-operator +images +test +test-unit +update +update-bindata +update-codegen +update-deps +update-deps-overrides +update-generated +update-gofmt +verify +verify-bindata +verify-codegen +verify-deps +verify-generated +verify-gofmt +verify-golint +verify-govet diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.mk new file mode 100644 index 0000000000..d763df4617 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/operator.mk @@ -0,0 +1,11 @@ +self_dir := $(dir $(lastword $(MAKEFILE_LIST))) + + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. +include $(addprefix $(self_dir), \ + default.mk \ + targets/openshift/operator/*.mk \ +) + diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/doc.go new file mode 100644 index 0000000000..66ba5512e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/doc.go @@ -0,0 +1,3 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/build.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/build.mk new file mode 100644 index 0000000000..9a71cb793a --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/build.mk @@ -0,0 +1,28 @@ +self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) + +define build-package + $(if $(GO_BUILD_BINDIR),mkdir -p '$(GO_BUILD_BINDIR)',) + $(strip $(GO) build $(GO_BUILD_FLAGS) $(GO_LD_FLAGS) \ + $(if $(GO_BUILD_BINDIR),-o '$(GO_BUILD_BINDIR)/$(notdir $(1))$(GOEXE)',) \ + $(1)) + +endef + +# We need to build each package separately so go build creates appropriate binaries +build: + $(foreach package,$(GO_BUILD_PACKAGES_EXPANDED),$(call build-package,$(package))) +.PHONY: build + +clean-binaries: + $(RM) $(go_build_binaries) +.PHONY: clean-binaries + +clean: clean-binaries +.PHONY: clean + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + ../../lib/golang.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/doc.go new file mode 100644 index 0000000000..66ba5512e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/doc.go @@ -0,0 +1,3 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/test-unit.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/test-unit.mk new file mode 100644 index 0000000000..f96c8ccd73 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/test-unit.mk @@ -0,0 +1,19 @@ +self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) + +test-unit: +ifndef JUNITFILE + $(GO) test $(GO_TEST_FLAGS) $(GO_TEST_PACKAGES) +else +ifeq (, $(shell which gotest2junit 2>/dev/null)) + $(error gotest2junit not found! Get it by `go get -u github.com/openshift/release/tools/gotest2junit`.) +endif + set -o pipefail; $(GO) test $(GO_TEST_FLAGS) -json $(GO_TEST_PACKAGES) | gotest2junit > $(JUNITFILE) +endif +.PHONY: test-unit + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + ../../lib/golang.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/verify-update.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/verify-update.mk new file mode 100644 index 0000000000..2034cd10e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/golang/verify-update.mk @@ -0,0 +1,34 @@ +self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) + +go_files_count :=$(words $(GO_FILES)) + +verify-gofmt: + $(info Running `$(GOFMT) $(GOFMT_FLAGS)` on $(go_files_count) file(s).) + @TMP=$$( mktemp ); \ + $(GOFMT) $(GOFMT_FLAGS) $(GO_FILES) | tee $${TMP}; \ + if [ -s $${TMP} ]; then \ + echo "$@ failed - please run \`make update-gofmt\`"; \ + exit 1; \ + fi; +.PHONY: verify-gofmt + +update-gofmt: + $(info Running `$(GOFMT) $(GOFMT_FLAGS) -w` on $(go_files_count) file(s).) + @$(GOFMT) $(GOFMT_FLAGS) -w $(GO_FILES) +.PHONY: update-gofmt + + +verify-govet: + $(GO) vet $(GO_PACKAGES) +.PHONY: verify-govet + +verify-golint: + $(GOLINT) $(GO_PACKAGES) +.PHONY: verify-govet + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + ../../lib/golang.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/help.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/help.mk new file mode 100644 index 0000000000..55bfbac094 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/help.mk @@ -0,0 +1,6 @@ +help: + $(info The following make targets are available:) + @$(MAKE) -f $(firstword $(MAKEFILE_LIST)) --print-data-base --question no-such-target 2>&1 | grep -v 'no-such-target' | \ + grep -v -e '^no-such-target' -e '^makefile' | \ + awk '/^[^.%][-A-Za-z0-9_]*:/ { print substr($$1, 1, length($$1)-1) }' | sort -u +.PHONY: help diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/bindata.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/bindata.mk new file mode 100644 index 0000000000..0e78cb9274 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/bindata.mk @@ -0,0 +1,65 @@ +TMP_GOPATH :=$(shell mktemp -d) + + +.ensure-go-bindata: + ln -s $(abspath ./vendor) "$(TMP_GOPATH)/src" + export GOPATH=$(TMP_GOPATH) && export GOBIN=$(TMP_GOPATH)/bin && go install "./vendor/github.com/jteeuwen/go-bindata/..." + +# $1 - input dirs +# $2 - prefix +# $3 - pkg +# $4 - output +# $5 - output prefix +define run-bindata + $(TMP_GOPATH)/bin/go-bindata -nocompress -nometadata \ + -prefix "$(2)" \ + -pkg "$(3)" \ + -o "$(5)$(4)" \ + -ignore "OWNERS" \ + $(1) && \ + gofmt -s -w "$(5)$(4)" +endef + +# $1 - name +# $2 - input dirs +# $3 - prefix +# $4 - pkg +# $5 - output +define add-bindata-internal +update-bindata-$(1): .ensure-go-bindata + $(call run-bindata,$(2),$(3),$(4),$(5),) +.PHONY: update-bindata-$(1) + +update-bindata: update-bindata-$(1) +.PHONY: update-bindata + + +verify-bindata-$(1): .ensure-go-bindata +verify-bindata-$(1): TMP_DIR := $$(shell mktemp -d) +verify-bindata-$(1): + $(call run-bindata,$(2),$(3),$(4),$(5),$$(TMP_DIR)/) && \ + diff -Naup {.,$$(TMP_DIR)}/$(5) +.PHONY: verify-bindata-$(1) + +verify-bindata: verify-bindata-$(1) +.PHONY: verify-bindata +endef + + +update-generated: update-bindata +.PHONY: update-bindata + +update: update-generated +.PHONY: update + + +verify-generated: verify-bindata +.PHONY: verify-bindata + +verify: verify-generated +.PHONY: verify + + +define add-bindata +$(eval $(call add-bindata-internal,$(1),$(2),$(3),$(4),$(5))) +endef diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/codegen.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/codegen.mk new file mode 100644 index 0000000000..247de9417c --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/codegen.mk @@ -0,0 +1,41 @@ +CODEGEN_PKG ?=./vendor/k8s.io/code-generator/ +CODEGEN_GENERATORS ?=all +CODEGEN_OUTPUT_BASE ?=../../.. +CODEGEN_GO_HEADER_FILE ?=/dev/null + +CODEGEN_API_PACKAGE ?=$(error CODEGEN_API_PACKAGE is required) +CODEGEN_GROUPS_VERSION ?=$(error CODEGEN_GROUPS_VERSION is required) +CODEGEN_OUTPUT_PACKAGE ?=$(error CODEGEN_OUTPUT_PACKAGE is required) + +define run-codegen +$(CODEGEN_PKG)/generate-groups.sh \ + "$(CODEGEN_GENERATORS)" \ + "$(CODEGEN_OUTPUT_PACKAGE)" \ + "$(CODEGEN_API_PACKAGE)" \ + "$(CODEGEN_GROUPS_VERSION)" \ + --output-base $(CODEGEN_OUTPUT_BASE) \ + --go-header-file $(CODEGEN_GO_HEADER_FILE) \ + $1 +endef + + +verify-codegen: + $(call run-codegen,--verify-only) +.PHONY: verify-codegen + +verify-generated: verify-codegen +.PHONY: verify-generated + +verify: verify-generated +.PHONY: verify + + +update-codegen: + $(call run-codegen) +.PHONY: update-codegen + +update-generated: update-codegen +.PHONY: update-generated + +update: update-generated +.PHONY: update diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/controller-gen.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/controller-gen.mk new file mode 100644 index 0000000000..8c9dcee7e0 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/controller-gen.mk @@ -0,0 +1,32 @@ +self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) + +CONTROLLER_GEN_VERSION ?=v0.2.1-37-ga3cca5d +CONTROLLER_GEN ?=$(PERMANENT_TMP_GOPATH)/bin/controller-gen +controller_gen_dir :=$(dir $(CONTROLLER_GEN)) + +ensure-controller-gen: +ifeq "" "$(wildcard $(CONTROLLER_GEN))" + $(info Installing controller-gen into '$(CONTROLLER_GEN)') + mkdir -p '$(controller_gen_dir)' + curl -s -f -L https://github.com/openshift/kubernetes-sigs-controller-tools/releases/download/$(CONTROLLER_GEN_VERSION)/controller-gen-$(GOHOSTOS)-$(GOHOSTARCH) -o '$(CONTROLLER_GEN)' + chmod +x '$(CONTROLLER_GEN)'; +else + $(info Using existing controller-gen from "$(CONTROLLER_GEN)") +endif +.PHONY: ensure-controller-gen + +clean-controller-gen: + $(RM) '$(CONTROLLER_GEN)' + if [ -d '$(controller_gen_dir)' ]; then rmdir --ignore-fail-on-non-empty -p '$(controller_gen_dir)'; fi +.PHONY: clean-controller-gen + +clean: clean-controller-gen + + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + ../../lib/golang.mk \ + ../../lib/tmp.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/crd-schema-gen.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/crd-schema-gen.mk new file mode 100644 index 0000000000..44963e96d1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/crd-schema-gen.mk @@ -0,0 +1,80 @@ +self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) + +# $1 - crd file +# $2 - patch file +define patch-crd + $(YQ) m -i -x '$(1)' '$(2)' + +endef + +empty := + +define diff-file + diff -Naup '$(1)' '$(2)' + +endef + +# $1 - apis +# $2 - manifests +# $3 - output +define run-crd-gen + '$(CONTROLLER_GEN)' \ + schemapatch:manifests="$(2)" \ + paths="$(subst $(empty) ,;,$(1))" \ + output:dir="$(3)" + $$(foreach p,$$(wildcard $(2)/*.crd.yaml-merge-patch),$$(call patch-crd,$$(subst $(2),$(3),$$(basename $$(p))).yaml,$$(p))) +endef + + +# $1 - target name +# $2 - apis +# $3 - manifests +# $4 - output +define add-crd-gen-internal + +update-codegen-crds-$(1): ensure-controller-gen ensure-yq + $(call run-crd-gen,$(2),$(3),$(4)) +.PHONY: update-codegen-crds-$(1) + +update-codegen-crds: update-codegen-crds-$(1) +.PHONY: update-codegen-crds + +verify-codegen-crds-$(1): VERIFY_CODEGEN_CRD_TMP_DIR:=$(shell mktemp -d) +verify-codegen-crds-$(1): ensure-controller-gen ensure-yq + $(call run-crd-gen,$(2),$(3),$$(VERIFY_CODEGEN_CRD_TMP_DIR)) + $$(foreach p,$$(wildcard $(3)/*.crd.yaml),$$(call diff-file,$$(p),$$(subst $(3),$$(VERIFY_CODEGEN_CRD_TMP_DIR),$$(p)))) +.PHONY: verify-codegen-crds-$(1) + +verify-codegen-crds: verify-codegen-crds-$(1) +.PHONY: verify-codegen-crds + +endef + + +update-generated: update-codegen-crds +.PHONY: update-generated + +update: update-generated +.PHONY: update + +verify-generated: verify-codegen-crds +.PHONY: verify-generated + +verify: verify-generated +.PHONY: verify + + +define add-crd-gen +$(eval $(call add-crd-gen-internal,$(1),$(2),$(3),$(4))) +endef + + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + ../../lib/golang.mk \ + ../../lib/tmp.mk \ + ../../targets/openshift/controller-gen.mk \ + ../../targets/openshift/yq.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/deps.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/deps.mk new file mode 100644 index 0000000000..fafa8f9dad --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/deps.mk @@ -0,0 +1,35 @@ +self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) +scripts_dir :=$(self_dir)/../../../scripts + +# We need to force localle so different envs sort files the same way for recursive traversals +deps_diff :=LC_COLLATE=C diff --no-dereference -N + +update-deps: + $(scripts_dir)/$@.sh +.PHONY: update-deps + +# $1 - temporary directory to restore vendor dependencies from glide.lock +define restore-deps + ln -s $(abspath ./) "$(1)"/current + cp -R -H ./ "$(1)"/updated + $(RM) -r "$(1)"/updated/vendor + cd "$(1)"/updated && glide install --strip-vendor && find ./vendor -name '.hg_archival.txt' -delete + cd "$(1)" && $(deps_diff) -r {current,updated}/vendor/ > updated/glide.diff || true +endef + +verify-deps: tmp_dir:=$(shell mktemp -d) +verify-deps: + $(call restore-deps,$(tmp_dir)) + @echo $(deps_diff) '$(tmp_dir)'/{current,updated}/glide.diff + @ $(deps_diff) '$(tmp_dir)'/{current,updated}/glide.diff || ( \ + echo "ERROR: Content of 'vendor/' directory doesn't match 'glide.lock' and the overrides in 'glide.diff'!" && \ + echo "If this is an intentional change (a carry patch) please update the 'glide.diff' using 'make update-deps-overrides'." && \ + exit 1 \ + ) +.PHONY: verify-deps + +update-deps-overrides: tmp_dir:=$(shell mktemp -d) +update-deps-overrides: + $(call restore-deps,$(tmp_dir)) + cp "$(tmp_dir)"/{updated,current}/glide.diff +.PHONY: update-deps-overrides diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/doc.go new file mode 100644 index 0000000000..66ba5512e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/doc.go @@ -0,0 +1,3 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/images.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/images.mk new file mode 100644 index 0000000000..00e76ac261 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/images.mk @@ -0,0 +1,29 @@ +# IMAGE_BUILD_EXTRA_FLAGS lets you add extra flags for imagebuilder +# e.g. to mount secrets and repo information into base image like: +# make images IMAGE_BUILD_EXTRA_FLAGS='-mount ~/projects/origin-repos/4.2/:/etc/yum.repos.d/' +IMAGE_BUILD_DEFAULT_FLAGS ?=--allow-pull +IMAGE_BUILD_EXTRA_FLAGS ?= + +# $1 - target name +# $2 - image ref +# $3 - Dockerfile path +# $4 - context +define build-image-internal +image-$(1): + $(strip \ + imagebuilder \ + $(IMAGE_BUILD_DEFAULT_FLAGS) \ + -t $(2) + -f $(3) \ + $(IMAGE_BUILD_EXTRA_FLAGS) \ + $(4) \ + ) +.PHONY: image-$(1) + +images: image-$(1) +.PHONY: images +endef + +define build-image +$(eval $(call build-image-internal,$(1),$(2),$(3),$(4))) +endef diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/operator/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/operator/doc.go new file mode 100644 index 0000000000..66ba5512e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/operator/doc.go @@ -0,0 +1,3 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/operator/release.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/operator/release.mk new file mode 100644 index 0000000000..07fc5605a8 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/operator/release.mk @@ -0,0 +1,7 @@ +# If we need unified behaviour specific to operators, this folder is the place. + +# It seems that our previous origin-release jq based replacement is suppose to be done +# with `oc adm release new` so it might drop this target. +#origin-release: +# $(error Not implemented.) +#.PHONY: origin-release diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/rpm.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/rpm.mk new file mode 100644 index 0000000000..b235197c74 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/rpm.mk @@ -0,0 +1,41 @@ +RPM_OUTPUT_DIR ?=_output +RPM_TOPDIR ?=$(abspath ./) +RPM_BUILDDIR ?=$(RPM_TOPDIR) +RPM_BUILDROOT ?=$(RPM_TOPDIR) +RPM_SOURCEDIR ?=$(RPM_TOPDIR) +RPM_SPECDIR ?=$(RPM_TOPDIR) +RPM_RPMDIR ?=$(RPM_TOPDIR)/$(RPM_OUTPUT_DIR)/rpms +RPM_SRCRPMDIR ?=$(RPM_TOPDIR)/$(RPM_OUTPUT_DIR)/srpms + +RPM_SPECFILES ?=$(wildcard *.spec) +RPM_BUILDFLAGS ?=-ba +RPM_EXTRAFLAGS ?= + +rpm-build: + $(strip \ + rpmbuild $(RPM_BUILDFLAGS) \ + --define "_topdir $(RPM_TOPDIR)" \ + --define "_builddir $(RPM_BUILDDIR)" \ + --define "_buildrootdir $(RPM_BUILDROOT)" \ + --define "_rpmdir $(RPM_RPMDIR)" \ + --define "_srcrpmdir $(RPM_SRCRPMDIR)" \ + --define "_specdir $(RPM_SPECDIR)" \ + --define "_sourcedir $(RPM_SOURCEDIR)" \ + --define "go_package $(GO_PACKAGE)" \ + $(RPM_EXTRAFLAGS) \ + $(RPM_SPECFILES) \ + ) + +clean-rpms: + $(RM) -r '$(RPM_RPMDIR)' '$(RPM_SRCRPMDIR)' + if [ -d '$(RPM_OUTPUT_DIR)' ]; then rmdir --ignore-fail-on-non-empty '$(RPM_OUTPUT_DIR)'; fi +.PHONY: clean-rpms + +clean: clean-rpms + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + ../../lib/golang.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/yq.mk b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/yq.mk new file mode 100644 index 0000000000..7dd556d400 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/make/targets/openshift/yq.mk @@ -0,0 +1,32 @@ +self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) + +YQ ?=$(PERMANENT_TMP_GOPATH)/bin/yq +yq_dir :=$(dir $(YQ)) + + +ensure-yq: +ifeq "" "$(wildcard $(YQ))" + $(info Installing yq into '$(YQ)') + mkdir -p '$(yq_dir)' + curl -s -f -L https://github.com/mikefarah/yq/releases/download/2.4.0/yq_$(GOHOSTOS)_$(GOHOSTARCH) -o '$(YQ)' + chmod +x '$(YQ)'; +else + $(info Using existing yq from "$(YQ)") +endif +.PHONY: ensure-yq + +clean-yq: + $(RM) '$(YQ)' + if [ -d '$(yq_dir)' ]; then rmdir --ignore-fail-on-non-empty -p '$(yq_dir)'; fi +.PHONY: clean-yq + +clean: clean-yq + + +# We need to be careful to expand all the paths before any include is done +# or self_dir could be modified for the next include by the included file. +# Also doing this at the end of the file allows us to user self_dir before it could be modified. +include $(addprefix $(self_dir), \ + ../../lib/golang.mk \ + ../../lib/tmp.mk \ +) diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/scripts/doc.go b/vendor/github.com/openshift/api/hack/alpha-build-machinery/scripts/doc.go new file mode 100644 index 0000000000..66ba5512e1 --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/scripts/doc.go @@ -0,0 +1,3 @@ +// required for gomod to pull in packages. + +package alpha_build_machinery diff --git a/vendor/github.com/openshift/api/hack/alpha-build-machinery/scripts/update-deps.sh b/vendor/github.com/openshift/api/hack/alpha-build-machinery/scripts/update-deps.sh new file mode 100755 index 0000000000..46812e939c --- /dev/null +++ b/vendor/github.com/openshift/api/hack/alpha-build-machinery/scripts/update-deps.sh @@ -0,0 +1,27 @@ +#!/bin/bash -e + +readonly GLIDE_MINOR_VERSION="13" +readonly REQUIRED_GLIDE_VERSION="0.$GLIDE_MINOR_VERSION" + +function verify_glide_version() { + if ! command -v glide &> /dev/null; then + echo "[FATAL] Glide was not found in \$PATH. Please install version ${REQUIRED_GLIDE_VERSION} or newer." + exit 1 + fi + + local glide_version + glide_version=($(glide --version)) + if ! echo "${glide_version[2]#v}" | awk -F. -v min=$GLIDE_MINOR_VERSION '{ exit $2 < min }'; then + echo "Detected glide version: ${glide_version[*]}." + echo "Please install Glide version ${REQUIRED_GLIDE_VERSION} or newer." + exit 1 + fi +} + +verify_glide_version + +glide update --strip-vendor + +# glide doesn't handle mercurial properly and leaves internal files (equivalent of .git/) laying around +# Given those files differ by mercurial version it was cloned with, verify-deps would break +find ./vendor -name '.hg_archival.txt' -delete diff --git a/vendor/github.com/openshift/api/hack/lib/init.sh b/vendor/github.com/openshift/api/hack/lib/init.sh index 9b2c2e7d6d..c270cb492f 100644 --- a/vendor/github.com/openshift/api/hack/lib/init.sh +++ b/vendor/github.com/openshift/api/hack/lib/init.sh @@ -30,7 +30,6 @@ security/v1 \ servicecertsigner/v1alpha1 \ template/v1 \ user/v1 \ -webconsole/v1 \ " API_PACKAGES="\ github.com/openshift/api/apps/v1,\ diff --git a/vendor/github.com/openshift/api/hack/update-deepcopy.sh b/vendor/github.com/openshift/api/hack/update-deepcopy.sh index b9a2a21ba3..fead8a958a 100755 --- a/vendor/github.com/openshift/api/hack/update-deepcopy.sh +++ b/vendor/github.com/openshift/api/hack/update-deepcopy.sh @@ -10,7 +10,7 @@ verify="${VERIFY:-}" ${CODEGEN_PKG}/generate-groups.sh "deepcopy" \ github.com/openshift/api/generated \ github.com/openshift/api \ - "apps:v1 authorization:v1 build:v1 config:v1 console:v1 image:v1,docker10,dockerpre012 kubecontrolplane:v1 legacyconfig:v1 network:v1 oauth:v1 openshiftcontrolplane:v1 operator:v1 operator:v1alpha1 osin:v1 project:v1 quota:v1 route:v1 security:v1 servicecertsigner:v1alpha1 template:v1 user:v1 webconsole:v1" \ + "apps:v1 authorization:v1 build:v1 config:v1 console:v1 image:v1,docker10,dockerpre012 kubecontrolplane:v1 legacyconfig:v1 network:v1 oauth:v1 openshiftcontrolplane:v1 operator:v1 operator:v1alpha1 osin:v1 project:v1 quota:v1 route:v1 security:v1 servicecertsigner:v1alpha1 template:v1 user:v1" \ --go-header-file ${SCRIPT_ROOT}/hack/empty.txt \ ${verify} diff --git a/vendor/github.com/openshift/api/hack/verify-crds.sh b/vendor/github.com/openshift/api/hack/verify-crds.sh new file mode 100755 index 0000000000..27f0b38cdf --- /dev/null +++ b/vendor/github.com/openshift/api/hack/verify-crds.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +if [ ! -f ./_output/tools/bin/yq ]; then + mkdir -p ./_output/tools/bin + curl -s -f -L https://github.com/mikefarah/yq/releases/download/2.4.0/yq_$(go env GOHOSTOS)_$(go env GOHOSTARCH) -o ./_output/tools/bin/yq + chmod +x ./_output/tools/bin/yq +fi + +FILES="config/v1/*.crd.yaml +authorization/v1/*.crd.yaml +console/v1/*.crd.yaml +operator/v1alpha1/*.crd.yaml +quota/v1/*.crd.yaml +security/v1/*.crd.yaml +" +for f in $FILES +do + if [[ $(./_output/tools/bin/yq r $f spec.validation.openAPIV3Schema.properties.metadata.description) != "null" ]]; then + echo "Error: cannot have a metadata description in $f" + exit 1 + fi +done diff --git a/vendor/github.com/openshift/api/image/v1/generated.proto b/vendor/github.com/openshift/api/image/v1/generated.proto index b390adc771..1a667589a6 100644 --- a/vendor/github.com/openshift/api/image/v1/generated.proto +++ b/vendor/github.com/openshift/api/image/v1/generated.proto @@ -33,7 +33,6 @@ message DockerImageReference { // Image is an immutable representation of a container image and metadata at a point in time. message Image { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // DockerImageReference is the string that can be used to pull this image. @@ -41,6 +40,7 @@ message Image { // DockerImageMetadata contains metadata about this image // +patchStrategy=replace + // +kubebuilder:validation:PreserveUnknownFields optional k8s.io.apimachinery.pkg.runtime.RawExtension dockerImageMetadata = 3; // DockerImageMetadataVersion conveys the version of the object, which if empty defaults to "1.0" @@ -142,7 +142,6 @@ message ImageLayerData { // ImageList is a list of Image objects. message ImageList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of images @@ -166,7 +165,6 @@ message ImageLookupPolicy { // Mandatory fields should be parsed by clients doing image verification. The others are parsed from // signature's content by the server. They serve just an informative purpose. message ImageSignature { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Required: Describes a type of stored blob. @@ -203,7 +201,6 @@ message ImageSignature { // when images are tagged in a stream, and an optional reference to a container image // repository on a registry. message ImageStream { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Spec describes the desired state of this stream @@ -215,7 +212,6 @@ message ImageStream { // ImageStreamImage represents an Image that is retrieved by image name from an ImageStream. message ImageStreamImage { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Image associated with the ImageStream and image name. @@ -231,7 +227,6 @@ message ImageStreamImage { // (for instance, to generate an application from it). Clients that know the desired image can continue // to create spec.tags directly into their image streams. message ImageStreamImport { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Spec is a description of the images that the user wishes to import @@ -270,7 +265,6 @@ message ImageStreamImportStatus { // ImageStreamLayers describes information about the layers referenced by images in this // image stream. message ImageStreamLayers { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // blobs is a map of blob name to metadata about the blob. @@ -283,7 +277,6 @@ message ImageStreamLayers { // ImageStreamList is a list of ImageStream objects. message ImageStreamList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of imageStreams @@ -293,7 +286,6 @@ message ImageStreamList { // ImageStreamMapping represents a mapping from a single tag to a container image as // well as the reference to the container image stream the image came from. message ImageStreamMapping { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Image is a container image. @@ -339,7 +331,6 @@ message ImageStreamStatus { // ImageStreamTag represents an Image that is retrieved by tag name from an ImageStream. message ImageStreamTag { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // tag is the spec tag associated with this image stream tag, and it may be null @@ -365,7 +356,6 @@ message ImageStreamTag { // ImageStreamTagList is a list of ImageStreamTag objects. message ImageStreamTagList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of image stream tags diff --git a/vendor/github.com/openshift/api/image/v1/types.go b/vendor/github.com/openshift/api/image/v1/types.go index 6524942500..ff89f400c0 100644 --- a/vendor/github.com/openshift/api/image/v1/types.go +++ b/vendor/github.com/openshift/api/image/v1/types.go @@ -11,7 +11,6 @@ import ( // ImageList is a list of Image objects. type ImageList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of images @@ -24,14 +23,14 @@ type ImageList struct { // Image is an immutable representation of a container image and metadata at a point in time. type Image struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // DockerImageReference is the string that can be used to pull this image. DockerImageReference string `json:"dockerImageReference,omitempty" protobuf:"bytes,2,opt,name=dockerImageReference"` // DockerImageMetadata contains metadata about this image // +patchStrategy=replace + // +kubebuilder:validation:PreserveUnknownFields DockerImageMetadata runtime.RawExtension `json:"dockerImageMetadata,omitempty" patchStrategy:"replace" protobuf:"bytes,3,opt,name=dockerImageMetadata"` // DockerImageMetadataVersion conveys the version of the object, which if empty defaults to "1.0" DockerImageMetadataVersion string `json:"dockerImageMetadataVersion,omitempty" protobuf:"bytes,4,opt,name=dockerImageMetadataVersion"` @@ -72,8 +71,7 @@ type ImageLayer struct { // Mandatory fields should be parsed by clients doing image verification. The others are parsed from // signature's content by the server. They serve just an informative purpose. type ImageSignature struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Required: Describes a type of stored blob. @@ -150,7 +148,6 @@ type SignatureSubject struct { // ImageStreamList is a list of ImageStream objects. type ImageStreamList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of imageStreams @@ -166,8 +163,7 @@ type ImageStreamList struct { // when images are tagged in a stream, and an optional reference to a container image // repository on a registry. type ImageStream struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Spec describes the desired state of this stream @@ -337,8 +333,7 @@ type TagEventCondition struct { // ImageStreamMapping represents a mapping from a single tag to a container image as // well as the reference to the container image stream the image came from. type ImageStreamMapping struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Image is a container image. @@ -353,8 +348,7 @@ type ImageStreamMapping struct { // ImageStreamTag represents an Image that is retrieved by tag name from an ImageStream. type ImageStreamTag struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // tag is the spec tag associated with this image stream tag, and it may be null @@ -383,7 +377,6 @@ type ImageStreamTag struct { // ImageStreamTagList is a list of ImageStreamTag objects. type ImageStreamTagList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is the list of image stream tags @@ -396,8 +389,7 @@ type ImageStreamTagList struct { // ImageStreamImage represents an Image that is retrieved by image name from an ImageStream. type ImageStreamImage struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Image associated with the ImageStream and image name. @@ -423,9 +415,9 @@ type DockerImageReference struct { // ImageStreamLayers describes information about the layers referenced by images in this // image stream. type ImageStreamLayers struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // blobs is a map of blob name to metadata about the blob. Blobs map[string]ImageLayerData `json:"blobs" protobuf:"bytes,2,rep,name=blobs"` // images is a map between an image name and the names of the blobs and config that @@ -474,8 +466,7 @@ type ImageLayerData struct { // (for instance, to generate an application from it). Clients that know the desired image can continue // to create spec.tags directly into their image streams. type ImageStreamImport struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Spec is a description of the images that the user wishes to import diff --git a/vendor/github.com/openshift/api/image/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/image/v1/zz_generated.swagger_doc_generated.go index a31b6316cb..43e67e620b 100644 --- a/vendor/github.com/openshift/api/image/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/image/v1/zz_generated.swagger_doc_generated.go @@ -26,7 +26,6 @@ func (DockerImageReference) SwaggerDoc() map[string]string { var map_Image = map[string]string{ "": "Image is an immutable representation of a container image and metadata at a point in time.", - "metadata": "Standard object's metadata.", "dockerImageReference": "DockerImageReference is the string that can be used to pull this image.", "dockerImageMetadata": "DockerImageMetadata contains metadata about this image", "dockerImageMetadataVersion": "DockerImageMetadataVersion conveys the version of the object, which if empty defaults to \"1.0\"", @@ -99,9 +98,8 @@ func (ImageLayerData) SwaggerDoc() map[string]string { } var map_ImageList = map[string]string{ - "": "ImageList is a list of Image objects.", - "metadata": "Standard object's metadata.", - "items": "Items is a list of images", + "": "ImageList is a list of Image objects.", + "items": "Items is a list of images", } func (ImageList) SwaggerDoc() map[string]string { @@ -119,7 +117,6 @@ func (ImageLookupPolicy) SwaggerDoc() map[string]string { var map_ImageSignature = map[string]string{ "": "ImageSignature holds a signature of an image. It allows to verify image identity and possibly other claims as long as the signature is trusted. Based on this information it is possible to restrict runnable images to those matching cluster-wide policy. Mandatory fields should be parsed by clients doing image verification. The others are parsed from signature's content by the server. They serve just an informative purpose.", - "metadata": "Standard object's metadata.", "type": "Required: Describes a type of stored blob.", "content": "Required: An opaque binary string which is an image's signature.", "conditions": "Conditions represent the latest available observations of a signature's current state.", @@ -135,10 +132,9 @@ func (ImageSignature) SwaggerDoc() map[string]string { } var map_ImageStream = map[string]string{ - "": "ImageStream stores a mapping of tags to images, metadata overrides that are applied when images are tagged in a stream, and an optional reference to a container image repository on a registry.", - "metadata": "Standard object's metadata.", - "spec": "Spec describes the desired state of this stream", - "status": "Status describes the current state of this stream", + "": "ImageStream stores a mapping of tags to images, metadata overrides that are applied when images are tagged in a stream, and an optional reference to a container image repository on a registry.", + "spec": "Spec describes the desired state of this stream", + "status": "Status describes the current state of this stream", } func (ImageStream) SwaggerDoc() map[string]string { @@ -146,9 +142,8 @@ func (ImageStream) SwaggerDoc() map[string]string { } var map_ImageStreamImage = map[string]string{ - "": "ImageStreamImage represents an Image that is retrieved by image name from an ImageStream.", - "metadata": "Standard object's metadata.", - "image": "Image associated with the ImageStream and image name.", + "": "ImageStreamImage represents an Image that is retrieved by image name from an ImageStream.", + "image": "Image associated with the ImageStream and image name.", } func (ImageStreamImage) SwaggerDoc() map[string]string { @@ -156,10 +151,9 @@ func (ImageStreamImage) SwaggerDoc() map[string]string { } var map_ImageStreamImport = map[string]string{ - "": "The image stream import resource provides an easy way for a user to find and import container images from other container image registries into the server. Individual images or an entire image repository may be imported, and users may choose to see the results of the import prior to tagging the resulting images into the specified image stream.\n\nThis API is intended for end-user tools that need to see the metadata of the image prior to import (for instance, to generate an application from it). Clients that know the desired image can continue to create spec.tags directly into their image streams.", - "metadata": "Standard object's metadata.", - "spec": "Spec is a description of the images that the user wishes to import", - "status": "Status is the the result of importing the image", + "": "The image stream import resource provides an easy way for a user to find and import container images from other container image registries into the server. Individual images or an entire image repository may be imported, and users may choose to see the results of the import prior to tagging the resulting images into the specified image stream.\n\nThis API is intended for end-user tools that need to see the metadata of the image prior to import (for instance, to generate an application from it). Clients that know the desired image can continue to create spec.tags directly into their image streams.", + "spec": "Spec is a description of the images that the user wishes to import", + "status": "Status is the the result of importing the image", } func (ImageStreamImport) SwaggerDoc() map[string]string { @@ -189,10 +183,9 @@ func (ImageStreamImportStatus) SwaggerDoc() map[string]string { } var map_ImageStreamLayers = map[string]string{ - "": "ImageStreamLayers describes information about the layers referenced by images in this image stream.", - "metadata": "Standard object's metadata.", - "blobs": "blobs is a map of blob name to metadata about the blob.", - "images": "images is a map between an image name and the names of the blobs and config that comprise the image.", + "": "ImageStreamLayers describes information about the layers referenced by images in this image stream.", + "blobs": "blobs is a map of blob name to metadata about the blob.", + "images": "images is a map between an image name and the names of the blobs and config that comprise the image.", } func (ImageStreamLayers) SwaggerDoc() map[string]string { @@ -200,9 +193,8 @@ func (ImageStreamLayers) SwaggerDoc() map[string]string { } var map_ImageStreamList = map[string]string{ - "": "ImageStreamList is a list of ImageStream objects.", - "metadata": "Standard object's metadata.", - "items": "Items is a list of imageStreams", + "": "ImageStreamList is a list of ImageStream objects.", + "items": "Items is a list of imageStreams", } func (ImageStreamList) SwaggerDoc() map[string]string { @@ -210,10 +202,9 @@ func (ImageStreamList) SwaggerDoc() map[string]string { } var map_ImageStreamMapping = map[string]string{ - "": "ImageStreamMapping represents a mapping from a single tag to a container image as well as the reference to the container image stream the image came from.", - "metadata": "Standard object's metadata.", - "image": "Image is a container image.", - "tag": "Tag is a string value this image can be located with inside the stream.", + "": "ImageStreamMapping represents a mapping from a single tag to a container image as well as the reference to the container image stream the image came from.", + "image": "Image is a container image.", + "tag": "Tag is a string value this image can be located with inside the stream.", } func (ImageStreamMapping) SwaggerDoc() map[string]string { @@ -244,7 +235,6 @@ func (ImageStreamStatus) SwaggerDoc() map[string]string { var map_ImageStreamTag = map[string]string{ "": "ImageStreamTag represents an Image that is retrieved by tag name from an ImageStream.", - "metadata": "Standard object's metadata.", "tag": "tag is the spec tag associated with this image stream tag, and it may be null if only pushes have occurred to this image stream.", "generation": "generation is the current generation of the tagged image - if tag is provided and this value is not equal to the tag generation, a user has requested an import that has not completed, or conditions will be filled out indicating any error.", "lookupPolicy": "lookupPolicy indicates whether this tag will handle image references in this namespace.", @@ -257,9 +247,8 @@ func (ImageStreamTag) SwaggerDoc() map[string]string { } var map_ImageStreamTagList = map[string]string{ - "": "ImageStreamTagList is a list of ImageStreamTag objects.", - "metadata": "Standard object's metadata.", - "items": "Items is the list of image stream tags", + "": "ImageStreamTagList is a list of ImageStreamTag objects.", + "items": "Items is the list of image stream tags", } func (ImageStreamTagList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/install.go b/vendor/github.com/openshift/api/install.go index 3fc1729a82..3dee1efbf4 100644 --- a/vendor/github.com/openshift/api/install.go +++ b/vendor/github.com/openshift/api/install.go @@ -51,7 +51,6 @@ import ( "github.com/openshift/api/servicecertsigner" "github.com/openshift/api/template" "github.com/openshift/api/user" - "github.com/openshift/api/webconsole" // just make sure this compiles. Don't add it to a scheme _ "github.com/openshift/api/legacyconfig/v1" @@ -77,7 +76,6 @@ var ( servicecertsigner.Install, template.Install, user.Install, - webconsole.Install, ) // Install is a function which adds every version of every openshift group to a scheme Install = schemeBuilder.AddToScheme diff --git a/vendor/github.com/openshift/api/network/v1/generated.proto b/vendor/github.com/openshift/api/network/v1/generated.proto index a5f3ccac78..62d0ace267 100644 --- a/vendor/github.com/openshift/api/network/v1/generated.proto +++ b/vendor/github.com/openshift/api/network/v1/generated.proto @@ -15,7 +15,6 @@ option go_package = "v1"; // named "default", which is created by the SDN network plugin based on the master configuration // when the cluster is brought up for the first time. message ClusterNetwork { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Network is a CIDR string specifying the global overlay network's L3 space @@ -30,7 +29,7 @@ message ClusterNetwork { // PluginName is the name of the network plugin being used optional string pluginName = 5; - // ClusterNetworks is a list of ClusterNetwork objects that defines the global overlay network's L3 space by specifying a set of CIDR and netmasks that the SDN can allocate addressed from. + // ClusterNetworks is a list of ClusterNetwork objects that defines the global overlay network's L3 space by specifying a set of CIDR and netmasks that the SDN can allocate addresses from. repeated ClusterNetworkEntry clusterNetworks = 6; // VXLANPort sets the VXLAN destination port used by the cluster. It is set by the master configuration file on startup and cannot be edited manually. Valid values for VXLANPort are integers 1-65535 inclusive and if unset defaults to 4789. Changing VXLANPort allows users to resolve issues between openshift SDN and other software trying to use the same VXLAN destination port. @@ -51,7 +50,6 @@ message ClusterNetworkEntry { // ClusterNetworkList is a collection of ClusterNetworks message ClusterNetworkList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of cluster networks @@ -64,7 +62,6 @@ message ClusterNetworkList { // namespace's EgressNetworkPolicy, in order. If no rule matches (or no EgressNetworkPolicy // is present) then the traffic will be allowed by default. message EgressNetworkPolicy { - // metadata for EgressNetworkPolicy optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // spec is the specification of the current egress network policy @@ -73,7 +70,6 @@ message EgressNetworkPolicy { // EgressNetworkPolicyList is a collection of EgressNetworkPolicy message EgressNetworkPolicyList { - // metadata for EgressNetworkPolicyList optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // items is the list of policies @@ -107,7 +103,6 @@ message EgressNetworkPolicySpec { // HostSubnet describes the container subnet network on a node. The HostSubnet object must have the // same name as the Node object it corresponds to. message HostSubnet { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Host is the name of the node. (This is the same as the object's name, but both fields must be set.) @@ -134,7 +129,6 @@ message HostSubnet { // HostSubnetList is a collection of HostSubnets message HostSubnetList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of host subnets @@ -145,7 +139,6 @@ message HostSubnetList { // plugin, every Namespace will have a corresponding NetNamespace object with the same name. // (When using redhat/openshift-ovs-subnet, NetNamespaces are not used.) message NetNamespace { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // NetName is the name of the network namespace. (This is the same as the object's name, but both fields must be set.) @@ -161,7 +154,6 @@ message NetNamespace { // NetNamespaceList is a collection of NetNamespaces message NetNamespaceList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of net namespaces diff --git a/vendor/github.com/openshift/api/network/v1/types.go b/vendor/github.com/openshift/api/network/v1/types.go index 52e4fd70ff..b8c6c5b53b 100644 --- a/vendor/github.com/openshift/api/network/v1/types.go +++ b/vendor/github.com/openshift/api/network/v1/types.go @@ -16,8 +16,7 @@ const ( // named "default", which is created by the SDN network plugin based on the master configuration // when the cluster is brought up for the first time. type ClusterNetwork struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Network is a CIDR string specifying the global overlay network's L3 space @@ -28,7 +27,7 @@ type ClusterNetwork struct { ServiceNetwork string `json:"serviceNetwork" protobuf:"bytes,4,opt,name=serviceNetwork"` // PluginName is the name of the network plugin being used PluginName string `json:"pluginName,omitempty" protobuf:"bytes,5,opt,name=pluginName"` - // ClusterNetworks is a list of ClusterNetwork objects that defines the global overlay network's L3 space by specifying a set of CIDR and netmasks that the SDN can allocate addressed from. + // ClusterNetworks is a list of ClusterNetwork objects that defines the global overlay network's L3 space by specifying a set of CIDR and netmasks that the SDN can allocate addresses from. ClusterNetworks []ClusterNetworkEntry `json:"clusterNetworks" protobuf:"bytes,6,rep,name=clusterNetworks"` // VXLANPort sets the VXLAN destination port used by the cluster. It is set by the master configuration file on startup and cannot be edited manually. Valid values for VXLANPort are integers 1-65535 inclusive and if unset defaults to 4789. Changing VXLANPort allows users to resolve issues between openshift SDN and other software trying to use the same VXLAN destination port. VXLANPort *uint32 `json:"vxlanPort,omitempty" protobuf:"varint,7,opt,name=vxlanPort"` @@ -49,8 +48,8 @@ type ClusterNetworkEntry struct { // ClusterNetworkList is a collection of ClusterNetworks type ClusterNetworkList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of cluster networks Items []ClusterNetwork `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -62,8 +61,7 @@ type ClusterNetworkList struct { // HostSubnet describes the container subnet network on a node. The HostSubnet object must have the // same name as the Node object it corresponds to. type HostSubnet struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Host is the name of the node. (This is the same as the object's name, but both fields must be set.) @@ -90,8 +88,8 @@ type HostSubnet struct { // HostSubnetList is a collection of HostSubnets type HostSubnetList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of host subnets Items []HostSubnet `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -104,8 +102,7 @@ type HostSubnetList struct { // plugin, every Namespace will have a corresponding NetNamespace object with the same name. // (When using redhat/openshift-ovs-subnet, NetNamespaces are not used.) type NetNamespace struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // NetName is the name of the network namespace. (This is the same as the object's name, but both fields must be set.) @@ -123,8 +120,8 @@ type NetNamespace struct { // NetNamespaceList is a collection of NetNamespaces type NetNamespaceList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of net namespaces Items []NetNamespace `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -168,8 +165,7 @@ type EgressNetworkPolicySpec struct { // namespace's EgressNetworkPolicy, in order. If no rule matches (or no EgressNetworkPolicy // is present) then the traffic will be allowed by default. type EgressNetworkPolicy struct { - metav1.TypeMeta `json:",inline"` - // metadata for EgressNetworkPolicy + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // spec is the specification of the current egress network policy @@ -181,8 +177,8 @@ type EgressNetworkPolicy struct { // EgressNetworkPolicyList is a collection of EgressNetworkPolicy type EgressNetworkPolicyList struct { metav1.TypeMeta `json:",inline"` - // metadata for EgressNetworkPolicyList metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // items is the list of policies Items []EgressNetworkPolicy `json:"items" protobuf:"bytes,2,rep,name=items"` } diff --git a/vendor/github.com/openshift/api/network/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/network/v1/zz_generated.swagger_doc_generated.go index a5457ac2eb..9a4b3a5bae 100644 --- a/vendor/github.com/openshift/api/network/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/network/v1/zz_generated.swagger_doc_generated.go @@ -13,12 +13,11 @@ package v1 // AUTO-GENERATED FUNCTIONS START HERE var map_ClusterNetwork = map[string]string{ "": "ClusterNetwork describes the cluster network. There is normally only one object of this type, named \"default\", which is created by the SDN network plugin based on the master configuration when the cluster is brought up for the first time.", - "metadata": "Standard object's metadata.", "network": "Network is a CIDR string specifying the global overlay network's L3 space", "hostsubnetlength": "HostSubnetLength is the number of bits of network to allocate to each node. eg, 8 would mean that each node would have a /24 slice of the overlay network for its pods", "serviceNetwork": "ServiceNetwork is the CIDR range that Service IP addresses are allocated from", "pluginName": "PluginName is the name of the network plugin being used", - "clusterNetworks": "ClusterNetworks is a list of ClusterNetwork objects that defines the global overlay network's L3 space by specifying a set of CIDR and netmasks that the SDN can allocate addressed from.", + "clusterNetworks": "ClusterNetworks is a list of ClusterNetwork objects that defines the global overlay network's L3 space by specifying a set of CIDR and netmasks that the SDN can allocate addresses from.", "vxlanPort": "VXLANPort sets the VXLAN destination port used by the cluster. It is set by the master configuration file on startup and cannot be edited manually. Valid values for VXLANPort are integers 1-65535 inclusive and if unset defaults to 4789. Changing VXLANPort allows users to resolve issues between openshift SDN and other software trying to use the same VXLAN destination port.", "mtu": "MTU is the MTU for the overlay network. This should be 50 less than the MTU of the network connecting the nodes. It is normally autodetected by the cluster network operator.", } @@ -38,9 +37,8 @@ func (ClusterNetworkEntry) SwaggerDoc() map[string]string { } var map_ClusterNetworkList = map[string]string{ - "": "ClusterNetworkList is a collection of ClusterNetworks", - "metadata": "Standard object's metadata.", - "items": "Items is the list of cluster networks", + "": "ClusterNetworkList is a collection of ClusterNetworks", + "items": "Items is the list of cluster networks", } func (ClusterNetworkList) SwaggerDoc() map[string]string { @@ -48,9 +46,8 @@ func (ClusterNetworkList) SwaggerDoc() map[string]string { } var map_EgressNetworkPolicy = map[string]string{ - "": "EgressNetworkPolicy describes the current egress network policy for a Namespace. When using the 'redhat/openshift-ovs-multitenant' network plugin, traffic from a pod to an IP address outside the cluster will be checked against each EgressNetworkPolicyRule in the pod's namespace's EgressNetworkPolicy, in order. If no rule matches (or no EgressNetworkPolicy is present) then the traffic will be allowed by default.", - "metadata": "metadata for EgressNetworkPolicy", - "spec": "spec is the specification of the current egress network policy", + "": "EgressNetworkPolicy describes the current egress network policy for a Namespace. When using the 'redhat/openshift-ovs-multitenant' network plugin, traffic from a pod to an IP address outside the cluster will be checked against each EgressNetworkPolicyRule in the pod's namespace's EgressNetworkPolicy, in order. If no rule matches (or no EgressNetworkPolicy is present) then the traffic will be allowed by default.", + "spec": "spec is the specification of the current egress network policy", } func (EgressNetworkPolicy) SwaggerDoc() map[string]string { @@ -58,9 +55,8 @@ func (EgressNetworkPolicy) SwaggerDoc() map[string]string { } var map_EgressNetworkPolicyList = map[string]string{ - "": "EgressNetworkPolicyList is a collection of EgressNetworkPolicy", - "metadata": "metadata for EgressNetworkPolicyList", - "items": "items is the list of policies", + "": "EgressNetworkPolicyList is a collection of EgressNetworkPolicy", + "items": "items is the list of policies", } func (EgressNetworkPolicyList) SwaggerDoc() map[string]string { @@ -98,7 +94,6 @@ func (EgressNetworkPolicySpec) SwaggerDoc() map[string]string { var map_HostSubnet = map[string]string{ "": "HostSubnet describes the container subnet network on a node. The HostSubnet object must have the same name as the Node object it corresponds to.", - "metadata": "Standard object's metadata.", "host": "Host is the name of the node. (This is the same as the object's name, but both fields must be set.)", "hostIP": "HostIP is the IP address to be used as a VTEP by other nodes in the overlay network", "subnet": "Subnet is the CIDR range of the overlay network assigned to the node for its pods", @@ -111,9 +106,8 @@ func (HostSubnet) SwaggerDoc() map[string]string { } var map_HostSubnetList = map[string]string{ - "": "HostSubnetList is a collection of HostSubnets", - "metadata": "Standard object's metadata.", - "items": "Items is the list of host subnets", + "": "HostSubnetList is a collection of HostSubnets", + "items": "Items is the list of host subnets", } func (HostSubnetList) SwaggerDoc() map[string]string { @@ -122,7 +116,6 @@ func (HostSubnetList) SwaggerDoc() map[string]string { var map_NetNamespace = map[string]string{ "": "NetNamespace describes a single isolated network. When using the redhat/openshift-ovs-multitenant plugin, every Namespace will have a corresponding NetNamespace object with the same name. (When using redhat/openshift-ovs-subnet, NetNamespaces are not used.)", - "metadata": "Standard object's metadata.", "netname": "NetName is the name of the network namespace. (This is the same as the object's name, but both fields must be set.)", "netid": "NetID is the network identifier of the network namespace assigned to each overlay network packet. This can be manipulated with the \"oc adm pod-network\" commands.", "egressIPs": "EgressIPs is a list of reserved IPs that will be used as the source for external traffic coming from pods in this namespace. (If empty, external traffic will be masqueraded to Node IPs.)", @@ -133,9 +126,8 @@ func (NetNamespace) SwaggerDoc() map[string]string { } var map_NetNamespaceList = map[string]string{ - "": "NetNamespaceList is a collection of NetNamespaces", - "metadata": "Standard object's metadata.", - "items": "Items is the list of net namespaces", + "": "NetNamespaceList is a collection of NetNamespaces", + "items": "Items is the list of net namespaces", } func (NetNamespaceList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/oauth/OWNERS b/vendor/github.com/openshift/api/oauth/OWNERS deleted file mode 100644 index f0e98440ac..0000000000 --- a/vendor/github.com/openshift/api/oauth/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -reviewers: - - enj diff --git a/vendor/github.com/openshift/api/oauth/v1/generated.proto b/vendor/github.com/openshift/api/oauth/v1/generated.proto index 4ffad7b811..e7a8c5c1e7 100644 --- a/vendor/github.com/openshift/api/oauth/v1/generated.proto +++ b/vendor/github.com/openshift/api/oauth/v1/generated.proto @@ -25,7 +25,6 @@ message ClusterRoleScopeRestriction { // OAuthAccessToken describes an OAuth access token message OAuthAccessToken { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // ClientName references the client that created this token. @@ -60,7 +59,6 @@ message OAuthAccessToken { // OAuthAccessTokenList is a collection of OAuth access tokens message OAuthAccessTokenList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of OAuth access tokens @@ -69,7 +67,6 @@ message OAuthAccessTokenList { // OAuthAuthorizeToken describes an OAuth authorization token message OAuthAuthorizeToken { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // ClientName references the client that created this token. @@ -103,7 +100,6 @@ message OAuthAuthorizeToken { // OAuthAuthorizeTokenList is a collection of OAuth authorization tokens message OAuthAuthorizeTokenList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of OAuth authorization tokens @@ -112,7 +108,6 @@ message OAuthAuthorizeTokenList { // OAuthClient describes an OAuth client message OAuthClient { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Secret is the unique secret associated with a client @@ -160,7 +155,6 @@ message OAuthClient { // OAuthClientAuthorization describes an authorization created by an OAuth client message OAuthClientAuthorization { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // ClientName references the client that created this authorization @@ -179,7 +173,6 @@ message OAuthClientAuthorization { // OAuthClientAuthorizationList is a collection of OAuth client authorizations message OAuthClientAuthorizationList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of OAuth client authorizations @@ -188,7 +181,6 @@ message OAuthClientAuthorizationList { // OAuthClientList is a collection of OAuth clients message OAuthClientList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of OAuth clients @@ -197,7 +189,6 @@ message OAuthClientList { // OAuthRedirectReference is a reference to an OAuth redirect object. message OAuthRedirectReference { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // The reference to an redirect object in the current namespace. diff --git a/vendor/github.com/openshift/api/oauth/v1/types.go b/vendor/github.com/openshift/api/oauth/v1/types.go index e62dbb4529..64bc173047 100644 --- a/vendor/github.com/openshift/api/oauth/v1/types.go +++ b/vendor/github.com/openshift/api/oauth/v1/types.go @@ -10,8 +10,7 @@ import ( // OAuthAccessToken describes an OAuth access token type OAuthAccessToken struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // ClientName references the client that created this token. @@ -50,8 +49,7 @@ type OAuthAccessToken struct { // OAuthAuthorizeToken describes an OAuth authorization token type OAuthAuthorizeToken struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // ClientName references the client that created this token. @@ -89,8 +87,7 @@ type OAuthAuthorizeToken struct { // OAuthClient describes an OAuth client type OAuthClient struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Secret is the unique secret associated with a client @@ -172,8 +169,7 @@ type ClusterRoleScopeRestriction struct { // OAuthClientAuthorization describes an authorization created by an OAuth client type OAuthClientAuthorization struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // ClientName references the client that created this authorization @@ -195,8 +191,8 @@ type OAuthClientAuthorization struct { // OAuthAccessTokenList is a collection of OAuth access tokens type OAuthAccessTokenList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of OAuth access tokens Items []OAuthAccessToken `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -206,8 +202,8 @@ type OAuthAccessTokenList struct { // OAuthAuthorizeTokenList is a collection of OAuth authorization tokens type OAuthAuthorizeTokenList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of OAuth authorization tokens Items []OAuthAuthorizeToken `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -217,8 +213,8 @@ type OAuthAuthorizeTokenList struct { // OAuthClientList is a collection of OAuth clients type OAuthClientList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of OAuth clients Items []OAuthClient `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -228,8 +224,8 @@ type OAuthClientList struct { // OAuthClientAuthorizationList is a collection of OAuth client authorizations type OAuthClientAuthorizationList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of OAuth client authorizations Items []OAuthClientAuthorization `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -238,9 +234,9 @@ type OAuthClientAuthorizationList struct { // OAuthRedirectReference is a reference to an OAuth redirect object. type OAuthRedirectReference struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // The reference to an redirect object in the current namespace. Reference RedirectReference `json:"reference,omitempty" protobuf:"bytes,2,opt,name=reference"` } diff --git a/vendor/github.com/openshift/api/oauth/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/oauth/v1/zz_generated.swagger_doc_generated.go index 5f7804b8eb..84ddf18ecd 100644 --- a/vendor/github.com/openshift/api/oauth/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/oauth/v1/zz_generated.swagger_doc_generated.go @@ -24,7 +24,6 @@ func (ClusterRoleScopeRestriction) SwaggerDoc() map[string]string { var map_OAuthAccessToken = map[string]string{ "": "OAuthAccessToken describes an OAuth access token", - "metadata": "Standard object's metadata.", "clientName": "ClientName references the client that created this token.", "expiresIn": "ExpiresIn is the seconds from CreationTime before this token expires.", "scopes": "Scopes is an array of the requested scopes.", @@ -41,9 +40,8 @@ func (OAuthAccessToken) SwaggerDoc() map[string]string { } var map_OAuthAccessTokenList = map[string]string{ - "": "OAuthAccessTokenList is a collection of OAuth access tokens", - "metadata": "Standard object's metadata.", - "items": "Items is the list of OAuth access tokens", + "": "OAuthAccessTokenList is a collection of OAuth access tokens", + "items": "Items is the list of OAuth access tokens", } func (OAuthAccessTokenList) SwaggerDoc() map[string]string { @@ -52,7 +50,6 @@ func (OAuthAccessTokenList) SwaggerDoc() map[string]string { var map_OAuthAuthorizeToken = map[string]string{ "": "OAuthAuthorizeToken describes an OAuth authorization token", - "metadata": "Standard object's metadata.", "clientName": "ClientName references the client that created this token.", "expiresIn": "ExpiresIn is the seconds from CreationTime before this token expires.", "scopes": "Scopes is an array of the requested scopes.", @@ -69,9 +66,8 @@ func (OAuthAuthorizeToken) SwaggerDoc() map[string]string { } var map_OAuthAuthorizeTokenList = map[string]string{ - "": "OAuthAuthorizeTokenList is a collection of OAuth authorization tokens", - "metadata": "Standard object's metadata.", - "items": "Items is the list of OAuth authorization tokens", + "": "OAuthAuthorizeTokenList is a collection of OAuth authorization tokens", + "items": "Items is the list of OAuth authorization tokens", } func (OAuthAuthorizeTokenList) SwaggerDoc() map[string]string { @@ -80,7 +76,6 @@ func (OAuthAuthorizeTokenList) SwaggerDoc() map[string]string { var map_OAuthClient = map[string]string{ "": "OAuthClient describes an OAuth client", - "metadata": "Standard object's metadata.", "secret": "Secret is the unique secret associated with a client", "additionalSecrets": "AdditionalSecrets holds other secrets that may be used to identify the client. This is useful for rotation and for service account token validation", "respondWithChallenges": "RespondWithChallenges indicates whether the client wants authentication needed responses made in the form of challenges instead of redirects", @@ -97,7 +92,6 @@ func (OAuthClient) SwaggerDoc() map[string]string { var map_OAuthClientAuthorization = map[string]string{ "": "OAuthClientAuthorization describes an authorization created by an OAuth client", - "metadata": "Standard object's metadata.", "clientName": "ClientName references the client that created this authorization", "userName": "UserName is the user name that authorized this client", "userUID": "UserUID is the unique UID associated with this authorization. UserUID and UserName must both match for this authorization to be valid.", @@ -109,9 +103,8 @@ func (OAuthClientAuthorization) SwaggerDoc() map[string]string { } var map_OAuthClientAuthorizationList = map[string]string{ - "": "OAuthClientAuthorizationList is a collection of OAuth client authorizations", - "metadata": "Standard object's metadata.", - "items": "Items is the list of OAuth client authorizations", + "": "OAuthClientAuthorizationList is a collection of OAuth client authorizations", + "items": "Items is the list of OAuth client authorizations", } func (OAuthClientAuthorizationList) SwaggerDoc() map[string]string { @@ -119,9 +112,8 @@ func (OAuthClientAuthorizationList) SwaggerDoc() map[string]string { } var map_OAuthClientList = map[string]string{ - "": "OAuthClientList is a collection of OAuth clients", - "metadata": "Standard object's metadata.", - "items": "Items is the list of OAuth clients", + "": "OAuthClientList is a collection of OAuth clients", + "items": "Items is the list of OAuth clients", } func (OAuthClientList) SwaggerDoc() map[string]string { @@ -130,7 +122,6 @@ func (OAuthClientList) SwaggerDoc() map[string]string { var map_OAuthRedirectReference = map[string]string{ "": "OAuthRedirectReference is a reference to an OAuth redirect object.", - "metadata": "Standard object's metadata.", "reference": "The reference to an redirect object in the current namespace.", } diff --git a/vendor/github.com/openshift/api/operator/v1/0000_20_kube-apiserver-operator_01_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_20_kube-apiserver-operator_01_config.crd.yaml new file mode 100644 index 0000000000..19ab3e5eb5 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_20_kube-apiserver-operator_01_config.crd.yaml @@ -0,0 +1,194 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: kubeapiservers.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: KubeAPIServer + plural: kubeapiservers + singular: kubeapiserver + preserveUnknownField: false + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: KubeAPIServer provides information to configure an operator to + manage kube-apiserver. + 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: + failedRevisionLimit: + description: failedRevisionLimit is the number of failed static pod + installer revisions to keep on disk and in the api -1 = unlimited, + 0 or unset = 5 (default) + format: int32 + type: integer + forceRedeploymentReason: + description: forceRedeploymentReason can be used to force the redeployment + of the operand by providing a unique string. This provides a mechanism + to kick a previously failed deployment and provide a reason why you + think it will work this time instead of failing again on the same + config. + type: string + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + pattern: ^(Managed|Force)$ + type: string + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + nullable: true + type: object + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + succeededRevisionLimit: + description: succeededRevisionLimit is the number of successful static + pod installer revisions to keep on disk and in the api -1 = unlimited, + 0 or unset = 5 (default) + format: int32 + type: integer + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + nullable: true + type: object + type: object + status: + properties: + conditions: + description: conditions is a list of conditions and their status + items: + description: OperatorCondition is just the standard condition fields. + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + format: int64 + type: integer + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + type: object + type: array + latestAvailableRevision: + description: latestAvailableRevision is the deploymentID of the most + recent deployment + format: int32 + type: integer + latestAvailableRevisionReason: + description: latestAvailableRevisionReason describe the detailed reason + for the most recent deployment + type: string + nodeStatuses: + description: nodeStatuses track the deployment values and errors across + individual nodes + items: + description: NodeStatus provides information about the current state + of a particular node managed by this operator. + properties: + currentRevision: + description: currentRevision is the generation of the most recently + successful deployment + format: int32 + type: integer + lastFailedRevision: + description: lastFailedRevision is the generation of the deployment + we tried and failed to deploy. + format: int32 + type: integer + lastFailedRevisionErrors: + description: lastFailedRevisionErrors is a list of the errors + during the failed deployment referenced in lastFailedRevision + items: + type: string + type: array + nodeName: + description: nodeName is the name of the node + type: string + targetRevision: + description: targetRevision is the generation of the deployment + we're trying to apply + format: int32 + type: integer + type: object + type: array + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + format: int64 + type: integer + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + format: int32 + type: integer + version: + description: version is the level this availability applies to + type: string + type: object + required: + - spec + type: object + version: v1 diff --git a/vendor/github.com/openshift/api/operator/v1/0000_20_kube-apiserver-operator_01_config.crd.yaml-merge-patch b/vendor/github.com/openshift/api/operator/v1/0000_20_kube-apiserver-operator_01_config.crd.yaml-merge-patch new file mode 100644 index 0000000000..be6a3cc2e7 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_20_kube-apiserver-operator_01_config.crd.yaml-merge-patch @@ -0,0 +1,8 @@ +spec: + validation: + openAPIV3Schema: + properties: + spec: + properties: + managementState: + pattern: "^(Managed|Force)$" \ No newline at end of file diff --git a/vendor/github.com/openshift/api/operator/v1/0000_25_kube-controller-manager-operator_01_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-controller-manager-operator_01_config.crd.yaml new file mode 100644 index 0000000000..8b424cf738 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-controller-manager-operator_01_config.crd.yaml @@ -0,0 +1,196 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: kubecontrollermanagers.operator.openshift.io +spec: + group: operator.openshift.io + names: + categories: + - coreoperators + kind: KubeControllerManager + plural: kubecontrollermanagers + singular: kubecontrollermanager + preserveUnknownField: false + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: KubeControllerManager provides information to configure an operator + to manage kube-controller-manager. + 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: + failedRevisionLimit: + description: failedRevisionLimit is the number of failed static pod + installer revisions to keep on disk and in the api -1 = unlimited, + 0 or unset = 5 (default) + format: int32 + type: integer + forceRedeploymentReason: + description: forceRedeploymentReason can be used to force the redeployment + of the operand by providing a unique string. This provides a mechanism + to kick a previously failed deployment and provide a reason why you + think it will work this time instead of failing again on the same + config. + type: string + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + pattern: ^(Managed|Force)$ + type: string + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + nullable: true + type: object + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + succeededRevisionLimit: + description: succeededRevisionLimit is the number of successful static + pod installer revisions to keep on disk and in the api -1 = unlimited, + 0 or unset = 5 (default) + format: int32 + type: integer + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + nullable: true + type: object + type: object + status: + properties: + conditions: + description: conditions is a list of conditions and their status + items: + description: OperatorCondition is just the standard condition fields. + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + format: int64 + type: integer + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + type: object + type: array + latestAvailableRevision: + description: latestAvailableRevision is the deploymentID of the most + recent deployment + format: int32 + type: integer + latestAvailableRevisionReason: + description: latestAvailableRevisionReason describe the detailed reason + for the most recent deployment + type: string + nodeStatuses: + description: nodeStatuses track the deployment values and errors across + individual nodes + items: + description: NodeStatus provides information about the current state + of a particular node managed by this operator. + properties: + currentRevision: + description: currentRevision is the generation of the most recently + successful deployment + format: int32 + type: integer + lastFailedRevision: + description: lastFailedRevision is the generation of the deployment + we tried and failed to deploy. + format: int32 + type: integer + lastFailedRevisionErrors: + description: lastFailedRevisionErrors is a list of the errors + during the failed deployment referenced in lastFailedRevision + items: + type: string + type: array + nodeName: + description: nodeName is the name of the node + type: string + targetRevision: + description: targetRevision is the generation of the deployment + we're trying to apply + format: int32 + type: integer + type: object + type: array + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + format: int64 + type: integer + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + format: int32 + type: integer + version: + description: version is the level this availability applies to + type: string + type: object + required: + - spec + type: object + version: v1 diff --git a/vendor/github.com/openshift/api/operator/v1/0000_25_kube-controller-manager-operator_01_config.crd.yaml-merge-patch b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-controller-manager-operator_01_config.crd.yaml-merge-patch new file mode 100644 index 0000000000..5cc312a439 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-controller-manager-operator_01_config.crd.yaml-merge-patch @@ -0,0 +1,10 @@ +# this file can be removed once we switch to v0.2 of crd generator +# see: https://github.com/openshift/cluster-kube-scheduler-operator/pull/148 +spec: + validation: + openAPIV3Schema: + properties: + spec: + properties: + managementState: + pattern: "^(Managed|Force)$" diff --git a/vendor/github.com/openshift/api/operator/v1/0000_25_kube-scheduler-operator_01_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-scheduler-operator_01_config.crd.yaml new file mode 100644 index 0000000000..fd589b0c37 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-scheduler-operator_01_config.crd.yaml @@ -0,0 +1,196 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: kubeschedulers.operator.openshift.io +spec: + group: operator.openshift.io + names: + categories: + - coreoperators + kind: KubeScheduler + plural: kubeschedulers + singular: kubescheduler + preserveUnknownField: false + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: KubeScheduler provides information to configure an operator to + manage scheduler. + 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: + failedRevisionLimit: + description: failedRevisionLimit is the number of failed static pod + installer revisions to keep on disk and in the api -1 = unlimited, + 0 or unset = 5 (default) + format: int32 + type: integer + forceRedeploymentReason: + description: forceRedeploymentReason can be used to force the redeployment + of the operand by providing a unique string. This provides a mechanism + to kick a previously failed deployment and provide a reason why you + think it will work this time instead of failing again on the same + config. + type: string + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + pattern: ^(Managed|Force)$ + type: string + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + nullable: true + type: object + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + succeededRevisionLimit: + description: succeededRevisionLimit is the number of successful static + pod installer revisions to keep on disk and in the api -1 = unlimited, + 0 or unset = 5 (default) + format: int32 + type: integer + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + nullable: true + type: object + type: object + status: + properties: + conditions: + description: conditions is a list of conditions and their status + items: + description: OperatorCondition is just the standard condition fields. + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + type: object + type: array + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + format: int64 + type: integer + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + type: object + type: array + latestAvailableRevision: + description: latestAvailableRevision is the deploymentID of the most + recent deployment + format: int32 + type: integer + latestAvailableRevisionReason: + description: latestAvailableRevisionReason describe the detailed reason + for the most recent deployment + type: string + nodeStatuses: + description: nodeStatuses track the deployment values and errors across + individual nodes + items: + description: NodeStatus provides information about the current state + of a particular node managed by this operator. + properties: + currentRevision: + description: currentRevision is the generation of the most recently + successful deployment + format: int32 + type: integer + lastFailedRevision: + description: lastFailedRevision is the generation of the deployment + we tried and failed to deploy. + format: int32 + type: integer + lastFailedRevisionErrors: + description: lastFailedRevisionErrors is a list of the errors + during the failed deployment referenced in lastFailedRevision + items: + type: string + type: array + nodeName: + description: nodeName is the name of the node + type: string + targetRevision: + description: targetRevision is the generation of the deployment + we're trying to apply + format: int32 + type: integer + type: object + type: array + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + format: int64 + type: integer + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + format: int32 + type: integer + version: + description: version is the level this availability applies to + type: string + type: object + required: + - spec + type: object + version: v1 diff --git a/vendor/github.com/openshift/api/operator/v1/0000_25_kube-scheduler-operator_01_config.crd.yaml-merge-patch b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-scheduler-operator_01_config.crd.yaml-merge-patch new file mode 100644 index 0000000000..5cc312a439 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_25_kube-scheduler-operator_01_config.crd.yaml-merge-patch @@ -0,0 +1,10 @@ +# this file can be removed once we switch to v0.2 of crd generator +# see: https://github.com/openshift/cluster-kube-scheduler-operator/pull/148 +spec: + validation: + openAPIV3Schema: + properties: + spec: + properties: + managementState: + pattern: "^(Managed|Force)$" diff --git a/vendor/github.com/openshift/api/operator/v1/0000_30_openshift-apiserver-operator_01_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_30_openshift-apiserver-operator_01_config.crd.yaml new file mode 100644 index 0000000000..7906640d6a --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_30_openshift-apiserver-operator_01_config.crd.yaml @@ -0,0 +1,135 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: openshiftapiservers.operator.openshift.io +spec: + scope: Cluster + preserveUnknownField: false + group: operator.openshift.io + version: v1 + names: + kind: OpenShiftAPIServer + plural: openshiftapiservers + singular: openshiftapiserver + categories: + - coreoperators + subresources: + status: {} + validation: + openAPIV3Schema: + description: OpenShiftAPIServer provides information to configure an operator + to manage openshift-apiserver. + type: object + required: + - spec + 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: + type: object + properties: + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + type: string + pattern: ^(Managed|Unmanaged|Force|Removed)$ + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + type: object + nullable: true + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + type: object + nullable: true + status: + type: object + properties: + conditions: + description: conditions is a list of conditions and their status + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + type: array + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + type: object + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + type: integer + format: int64 + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + type: integer + format: int64 + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + type: integer + format: int32 + version: + description: version is the level this availability applies to + type: string diff --git a/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-authentication-operator_01_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-authentication-operator_01_config.crd.yaml new file mode 100644 index 0000000000..53d5ecdcca --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-authentication-operator_01_config.crd.yaml @@ -0,0 +1,133 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: authentications.operator.openshift.io +spec: + scope: Cluster + preserveUnknownField: false + group: operator.openshift.io + version: v1 + names: + kind: Authentication + plural: authentications + singular: authentication + subresources: + status: {} + validation: + openAPIV3Schema: + description: Authentication provides information to configure an operator to + manage authentication. + type: object + required: + - spec + 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: + type: object + properties: + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + type: string + pattern: ^(Managed|Unmanaged|Force|Removed)$ + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + type: object + nullable: true + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + type: object + nullable: true + status: + type: object + properties: + conditions: + description: conditions is a list of conditions and their status + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + type: array + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + type: object + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + type: integer + format: int64 + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + type: integer + format: int64 + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + type: integer + format: int32 + version: + description: version is the level this availability applies to + type: string diff --git a/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-openshift-controller-manager-operator_02_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-openshift-controller-manager-operator_02_config.crd.yaml new file mode 100644 index 0000000000..bf16fe076a --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-openshift-controller-manager-operator_02_config.crd.yaml @@ -0,0 +1,135 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: openshiftcontrollermanagers.operator.openshift.io +spec: + scope: Cluster + preserveUnknownField: false + group: operator.openshift.io + version: v1 + names: + kind: OpenShiftControllerManager + plural: openshiftcontrollermanagers + singular: openshiftcontrollermanager + categories: + - coreoperators + subresources: + status: {} + validation: + openAPIV3Schema: + description: OpenShiftControllerManager provides information to configure an + operator to manage openshift-controller-manager. + type: object + required: + - spec + 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: + type: object + properties: + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + type: string + pattern: ^(Managed|Unmanaged|Force|Removed)$ + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + type: object + nullable: true + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + type: object + nullable: true + status: + type: object + properties: + conditions: + description: conditions is a list of conditions and their status + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + type: array + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + type: object + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + type: integer + format: int64 + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + type: integer + format: int64 + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + type: integer + format: int32 + version: + description: version is the level this availability applies to + type: string diff --git a/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-svcat-apiserver-operator_02_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-svcat-apiserver-operator_02_config.crd.yaml new file mode 100644 index 0000000000..7919e5588e --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-svcat-apiserver-operator_02_config.crd.yaml @@ -0,0 +1,135 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: servicecatalogapiservers.operator.openshift.io +spec: + scope: Cluster + preserveUnknownField: false + group: operator.openshift.io + version: v1 + names: + kind: ServiceCatalogAPIServer + plural: servicecatalogapiservers + singular: servicecatalogapiserver + categories: + - coreoperators + subresources: + status: {} + validation: + openAPIV3Schema: + description: ServiceCatalogAPIServer provides information to configure an operator + to manage Service Catalog API Server + type: object + required: + - spec + 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: + type: object + properties: + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + type: string + pattern: ^(Managed|Unmanaged|Force|Removed)$ + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + type: object + nullable: true + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + type: object + nullable: true + status: + type: object + properties: + conditions: + description: conditions is a list of conditions and their status + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + type: array + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + type: object + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + type: integer + format: int64 + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + type: integer + format: int64 + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + type: integer + format: int32 + version: + description: version is the level this availability applies to + type: string diff --git a/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-svcat-controller-manager-operator_02_config.crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-svcat-controller-manager-operator_02_config.crd.yaml new file mode 100644 index 0000000000..ecb6f678db --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_50_cluster-svcat-controller-manager-operator_02_config.crd.yaml @@ -0,0 +1,135 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: servicecatalogcontrollermanagers.operator.openshift.io +spec: + scope: Cluster + preserveUnknownField: false + group: operator.openshift.io + version: v1 + names: + kind: ServiceCatalogControllerManager + plural: servicecatalogcontrollermanagers + singular: servicecatalogcontrollermanager + categories: + - coreoperators + subresources: + status: {} + validation: + openAPIV3Schema: + description: ServiceCatalogControllerManager provides information to configure + an operator to manage Service Catalog Controller Manager + type: object + required: + - spec + 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: + type: object + properties: + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + type: string + pattern: ^(Managed|Unmanaged|Force|Removed)$ + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + type: object + nullable: true + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + type: object + nullable: true + status: + type: object + properties: + conditions: + description: conditions is a list of conditions and their status + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + type: array + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + type: object + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + type: integer + format: int64 + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + type: integer + format: int64 + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + type: integer + format: int32 + version: + description: version is the level this availability applies to + type: string diff --git a/vendor/github.com/openshift/api/operator/v1/0000_50_service-ca-operator_02_crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_50_service-ca-operator_02_crd.yaml new file mode 100644 index 0000000000..0c30d1ec15 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_50_service-ca-operator_02_crd.yaml @@ -0,0 +1,136 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: servicecas.operator.openshift.io +spec: + scope: Cluster + preserveUnknownField: false + group: operator.openshift.io + version: v1 + names: + kind: ServiceCA + plural: servicecas + singular: serviceca + subresources: + status: {} + validation: + openAPIV3Schema: + description: ServiceCA provides information to configure an operator to manage + the service cert controllers + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + logLevel: + description: logLevel is an intent based logging for an overall component. It + does not give fine grained control, but it is a simple way to manage + coarse grained logging choices that operators have to interpret for + their operands. + type: string + managementState: + description: managementState indicates whether and how the operator + should manage the component + type: string + pattern: ^(Managed|Unmanaged|Force|Removed)$ + observedConfig: + description: observedConfig holds a sparse config that controller has + observed from the cluster state. It exists in spec because it is + an input to the level for the operator + type: object + nullable: true + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have to + interpret for themselves. + type: string + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + type: object + nullable: true + status: + description: status holds observed values from the cluster. They may not + be overridden. + type: object + properties: + conditions: + description: conditions is a list of conditions and their status + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + generations: + description: generations are used to determine when an item needs to + be reconciled or has changed in a way that needs a reaction. + type: array + items: + description: GenerationStatus keeps track of the generation for a + given resource so that decisions about forced updates can be made. + type: object + properties: + group: + description: group is the group of the thing you're tracking + type: string + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps + type: string + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + type: integer + format: int64 + name: + description: name is the name of the thing you're tracking + type: string + namespace: + description: namespace is where the thing you're tracking is + type: string + resource: + description: resource is the resource type of the thing you're + tracking + type: string + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + type: integer + format: int64 + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + type: integer + format: int32 + version: + description: version is the level this availability applies to + type: string diff --git a/vendor/github.com/openshift/api/operator/v1/0000_70_cluster-network-operator_01_crd.yaml b/vendor/github.com/openshift/api/operator/v1/0000_70_cluster-network-operator_01_crd.yaml new file mode 100644 index 0000000000..d49027d79d --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_70_cluster-network-operator_01_crd.yaml @@ -0,0 +1,332 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: networks.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: Network + listKind: NetworkList + plural: networks + singular: network + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + validation: + # Ensure we will be able to deserialize the object into the golang type + openAPIV3Schema: + description: Network describes the cluster's desired network configuration. + It is consumed by the cluster-network-operator. + type: object + 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: + description: NetworkSpec is the top-level network configuration object. + type: object + properties: + additionalNetworks: + description: additionalNetworks is a list of extra networks to make + available to pods when multiple networks are enabled. + type: array + items: + description: AdditionalNetworkDefinition configures an extra network + that is available but not created by default. Instead, pods must + request them by name. type must be specified, along with exactly + one "Config" that matches the type. + type: object + properties: + name: + description: name is the name of the network. This will be populated + in the resulting CRD This must be unique. + type: string + namespace: + description: namespace is the namespace of the network. This will + be populated in the resulting CRD If not given the network will + be created in the default namespace. + type: string + rawCNIConfig: + description: rawCNIConfig is the raw CNI configuration json to + create in the NetworkAttachmentDefinition CRD + type: string + simpleMacvlanConfig: + description: SimpleMacvlanConfig configures the macvlan interface + in case of type:NetworkTypeSimpleMacvlan + type: object + properties: + ipamConfig: + description: IPAMConfig configures IPAM module will be used + for IP Address Management (IPAM). + type: object + properties: + staticIPAMConfig: + description: StaticIPAMConfig configures the static IP + address in case of type:IPAMTypeStatic + type: object + properties: + addresses: + description: Addresses configures IP address for the + interface + type: array + items: + description: StaticIPAMAddresses provides IP address + and Gateway for static IPAM addresses + type: object + properties: + address: + description: Address is the IP address in CIDR + format + type: string + gateway: + description: Gateway is IP inside of subnet + to designate as the gateway + type: string + dns: + description: DNS configures DNS for the interface + type: object + properties: + domain: + description: Domain configures the domainname + the local domain used for short hostname lookups + type: string + nameservers: + description: Nameservers points DNS servers for + IP lookup + type: array + items: + type: string + search: + description: Search configures priority ordered + search domains for short hostname lookups + type: array + items: + type: string + routes: + description: Routes configures IP routes for the interface + type: array + items: + description: StaticIPAMRoutes provides Destination/Gateway + pairs for static IPAM routes + type: object + properties: + destination: + description: Destination points the IP route + destination + type: string + gateway: + description: Gateway is the route's next-hop + IP address If unset, a default gateway is + assumed (as determined by the CNI plugin). + type: string + type: + description: Type is the type of IPAM module will be used + for IP Address Management(IPAM). The supported values + are IPAMTypeDHCP, IPAMTypeStatic + type: string + master: + description: master is the host interface to create the macvlan + interface from. If not specified, it will be default route + interface + type: string + mode: + description: 'mode is the macvlan mode: bridge, private, vepa, + passthru. The default is bridge' + type: string + mtu: + description: mtu is the mtu to use for the macvlan interface. + if unset, host's kernel will select the value. + type: integer + format: int32 + minimum: 0 + type: + description: type is the type of network The supported values + are NetworkTypeRaw, NetworkTypeSimpleMacvlan + type: string + clusterNetwork: + description: clusterNetwork is the IP address pool to use for pod IPs. + Some network providers, e.g. OpenShift SDN, support multiple ClusterNetworks. + Others only support one. This is equivalent to the cluster-cidr. + type: array + items: + description: ClusterNetworkEntry is a subnet from which to allocate + PodIPs. A network of size HostPrefix (in CIDR notation) will be + allocated when nodes join the cluster. Not all network providers + support multiple ClusterNetworks + type: object + properties: + cidr: + type: string + hostPrefix: + type: integer + format: int32 + minimum: 0 + defaultNetwork: + description: defaultNetwork is the "default" network that all pods will + receive + type: object + properties: + kuryrConfig: + description: KuryrConfig configures the kuryr plugin + type: object + properties: + controllerProbesPort: + description: The port kuryr-controller will listen for readiness + and liveness requests. + type: integer + format: int32 + minimum: 0 + daemonProbesPort: + description: The port kuryr-daemon will listen for readiness + and liveness requests. + type: integer + format: int32 + minimum: 0 + openStackServiceNetwork: + description: openStackServiceNetwork contains the CIDR of network + from which to allocate IPs for OpenStack Octavia's Amphora + VMs. Please note that with Amphora driver Octavia uses two + IPs from that network for each loadbalancer - one given by + OpenShift and second for VRRP connections. As the first one + is managed by OpenShift's and second by Neutron's IPAMs, those + need to come from different pools. Therefore `openStackServiceNetwork` + needs to be at least twice the size of `serviceNetwork`, and + whole `serviceNetwork` must be overlapping with `openStackServiceNetwork`. + cluster-network-operator will then make sure VRRP IPs are + taken from the ranges inside `openStackServiceNetwork` that + are not overlapping with `serviceNetwork`, effectivly preventing + conflicts. If not set cluster-network-operator will use `serviceNetwork` + expanded by decrementing the prefix size by 1. + type: string + openshiftSDNConfig: + description: openShiftSDNConfig configures the openshift-sdn plugin + type: object + properties: + enableUnidling: + description: enableUnidling controls whether or not the service + proxy will support idling and unidling of services. By default, + unidling is enabled. + type: boolean + mode: + description: mode is one of "Multitenant", "Subnet", or "NetworkPolicy" + type: string + mtu: + description: mtu is the mtu to use for the tunnel interface. + Defaults to 1450 if unset. This must be 50 bytes smaller than + the machine's uplink. + type: integer + format: int32 + minimum: 0 + useExternalOpenvswitch: + description: useExternalOpenvswitch tells the operator not to + install openvswitch, because it will be provided separately. + If set, you must provide it yourself. + type: boolean + vxlanPort: + description: vxlanPort is the port to use for all vxlan packets. + The default is 4789. + type: integer + format: int32 + minimum: 0 + ovnKubernetesConfig: + description: oVNKubernetesConfig configures the ovn-kubernetes plugin. + This is currently not implemented. + type: object + properties: + genevePort: + description: geneve port is the UDP port to be used by geneve + encapulation. Default is 6081 + type: integer + format: int32 + minimum: 1 + hybridOverlayConfig: + description: HybridOverlayConfig configures an additional overlay + network for peers that are not using OVN. + type: object + properties: + hybridClusterNetwork: + description: HybridClusterNetwork defines a network space + given to nodes on an additional overlay network. + type: array + items: + description: ClusterNetworkEntry is a subnet from which + to allocate PodIPs. A network of size HostPrefix (in + CIDR notation) will be allocated when nodes join the + cluster. Not all network providers support multiple + ClusterNetworks + type: object + properties: + cidr: + type: string + hostPrefix: + type: integer + format: int32 + minimum: 0 + mtu: + description: mtu is the MTU to use for the tunnel interface. + This must be 100 bytes smaller than the uplink mtu. Default + is 1400 + type: integer + format: int32 + minimum: 0 + type: + description: type is the type of network All NetworkTypes are supported + except for NetworkTypeRaw + type: string + deployKubeProxy: + description: deployKubeProxy specifies whether or not a standalone kube-proxy + should be deployed by the operator. Some network providers include + kube-proxy or similar functionality. If unset, the plugin will attempt + to select the correct value, which is false when OpenShift SDN and + ovn-kubernetes are used and true otherwise. + type: boolean + disableMultiNetwork: + description: disableMultiNetwork specifies whether or not multiple pod + network support should be disabled. If unset, this property defaults + to 'false' and multiple network support is enabled. + type: boolean + kubeProxyConfig: + description: kubeProxyConfig lets us configure desired proxy configuration. + If not specified, sensible defaults will be chosen by OpenShift directly. + Not consumed by all network providers - currently only openshift-sdn. + type: object + properties: + bindAddress: + description: The address to "bind" on Defaults to 0.0.0.0 + type: string + iptablesSyncPeriod: + description: 'The period that iptables rules are refreshed. Default: + 30s' + type: string + proxyArguments: + description: Any additional arguments to pass to the kubeproxy process + type: object + additionalProperties: + description: ProxyArgumentList is a list of arguments to pass + to the kubeproxy process + type: array + items: + type: string + serviceNetwork: + description: serviceNetwork is the ip address pool to use for Service + IPs Currently, all existing network providers only support a single + value here, but this is an array to allow for growth. + type: array + items: + type: string + status: + description: NetworkStatus is currently unused. Instead, status is reported + in the Network.config.openshift.io object. + type: object diff --git a/vendor/github.com/openshift/api/operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml b/vendor/github.com/openshift/api/operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml new file mode 100644 index 0000000000..a1e44cd197 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/0000_70_dns-operator_00-custom-resource-definition.yaml @@ -0,0 +1,94 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: dnses.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: DNS + listKind: DNSList + plural: dnses + singular: dns + scope: Cluster + preserveUnknownField: false + subresources: + status: {} + validation: + openAPIV3Schema: + description: "DNS manages the CoreDNS component to provide a name resolution + service for pods and services in the cluster. \n This supports the DNS-based + service discovery specification: https://github.com/kubernetes/dns/blob/master/docs/specification.md + \n More details: https://kubernetes.io/docs/tasks/administer-cluster/coredns" + type: object + 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: + description: spec is the specification of the desired behavior of the DNS. + type: object + status: + description: status is the most recently observed status of the DNS. + type: object + required: + - clusterDomain + - clusterIP + properties: + clusterDomain: + description: "clusterDomain is the local cluster DNS domain suffix for + DNS services. This will be a subdomain as defined in RFC 1034, section + 3.5: https://tools.ietf.org/html/rfc1034#section-3.5 Example: \"cluster.local\" + \n More info: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service" + type: string + clusterIP: + description: "clusterIP is the service IP through which this DNS is + made available. \n In the case of the default DNS, this will be a + well known IP that is used as the default nameserver for pods that + are using the default ClusterFirst DNS policy. \n In general, this + IP can be specified in a pod's spec.dnsConfig.nameservers list or + used explicitly when performing name resolution from within the cluster. + Example: dig foo.com @ \n More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies" + type: string + conditions: + description: "conditions provide information about the state of the + DNS on the cluster. \n These are the supported DNS conditions: \n + \ * Available - True if the following conditions are met: * + DNS controller daemonset is available. - False if any of those conditions + are unsatisfied." + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + version: v1 + versions: + - name: v1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/vendor/github.com/openshift/api/operator/v1/register.go b/vendor/github.com/openshift/api/operator/v1/register.go index 423a41a9af..ab0b1ffa7f 100644 --- a/vendor/github.com/openshift/api/operator/v1/register.go +++ b/vendor/github.com/openshift/api/operator/v1/register.go @@ -46,6 +46,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &KubeControllerManagerList{}, &KubeScheduler{}, &KubeSchedulerList{}, + &KubeStorageVersionMigrator{}, + &KubeStorageVersionMigratorList{}, &Network{}, &NetworkList{}, &OpenShiftAPIServer{}, diff --git a/vendor/github.com/openshift/api/operator/v1/types.go b/vendor/github.com/openshift/api/operator/v1/types.go index 179c476c63..351e35ab47 100644 --- a/vendor/github.com/openshift/api/operator/v1/types.go +++ b/vendor/github.com/openshift/api/operator/v1/types.go @@ -24,7 +24,7 @@ type MyOperatorResourceStatus struct { OperatorStatus `json:",inline"` } -// +kubebuilder:validation:Pattern=^(Managed|Unmanaged|Force|Removed)$ +// +kubebuilder:validation:Pattern=`^(Managed|Unmanaged|Force|Removed)$` type ManagementState string var ( @@ -66,12 +66,14 @@ type OperatorSpec struct { // 3. unsupportedConfigOverrides // +optional // +nullable + // +kubebuilder:validation:PreserveUnknownFields UnsupportedConfigOverrides runtime.RawExtension `json:"unsupportedConfigOverrides"` // observedConfig holds a sparse config that controller has observed from the cluster state. It exists in spec because // it is an input to the level for the operator // +optional // +nullable + // +kubebuilder:validation:PreserveUnknownFields ObservedConfig runtime.RawExtension `json:"observedConfig"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_dns.go b/vendor/github.com/openshift/api/operator/v1/types_dns.go index 467696bb5b..5172dbe77f 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_dns.go +++ b/vendor/github.com/openshift/api/operator/v1/types_dns.go @@ -49,6 +49,9 @@ type DNSStatus struct { // Example: dig foo.com @ // // More info: https://kubernetes.io/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies + // + // +kubebuilder:validation:Required + // +required ClusterIP string `json:"clusterIP"` // clusterDomain is the local cluster DNS domain suffix for DNS services. @@ -57,6 +60,9 @@ type DNSStatus struct { // Example: "cluster.local" // // More info: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service + // + // +kubebuilder:validation:Required + // +required ClusterDomain string `json:"clusterDomain"` // conditions provide information about the state of the DNS on the cluster. diff --git a/vendor/github.com/openshift/api/operator/v1/types_etcd.go b/vendor/github.com/openshift/api/operator/v1/types_etcd.go index ad75154bd3..6a2fbdb9ac 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_etcd.go +++ b/vendor/github.com/openshift/api/operator/v1/types_etcd.go @@ -33,8 +33,8 @@ type EtcdStatus struct { // KubeAPISOperatorConfigList is a collection of items type EtcdList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []Etcd `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_ingress.go b/vendor/github.com/openshift/api/operator/v1/types_ingress.go index 1d119b5b4d..d3bfb3c83d 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_ingress.go +++ b/vendor/github.com/openshift/api/operator/v1/types_ingress.go @@ -4,6 +4,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" corev1 "k8s.io/api/core/v1" + + configv1 "github.com/openshift/api/config/v1" ) // +genclient @@ -125,6 +127,19 @@ type IngressControllerSpec struct { // // +optional NodePlacement *NodePlacement `json:"nodePlacement,omitempty"` + + // tlsSecurityProfile specifies settings for TLS connections for ingresscontrollers. + // + // If unset, the default is based on the apiservers.config.openshift.io/cluster resource. + // + // Note that when using the Old, Intermediate, and Modern profile types, the effective + // profile configuration is subject to change between releases. For example, given + // a specification to use the Intermediate profile deployed on release X.Y.Z, an upgrade + // to release X.Y.Z+1 may cause a new profile configuration to be applied to the ingress + // controller, resulting in a rollout. + // + // +optional + TLSSecurityProfile *configv1.TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"` } // NodePlacement describes node scheduling configuration for an ingress @@ -217,7 +232,7 @@ type EndpointPublishingStrategy struct { // In this configuration, the ingress controller deployment uses container // networking. A LoadBalancer Service is created to publish the deployment. // - // See: https://kubernetes.io/docs/concepts/services-networking/#loadbalancer + // See: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer // // If domain is set, a wildcard DNS record will be managed to point at the // LoadBalancer Service's external name. DNS records are managed only in DNS @@ -332,6 +347,14 @@ type IngressControllerStatus struct { // * DNS records have been successfully created. // - False if any of those conditions are unsatisfied. Conditions []OperatorCondition `json:"conditions,omitempty"` + + // tlsProfile is the TLS connection configuration that is in effect. + // +optional + TLSProfile *configv1.TLSProfileSpec `json:"tlsProfile,omitempty"` + + // observedGeneration is the most recent generation observed. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/api/operator/v1/types_kubeapiserver.go b/vendor/github.com/openshift/api/operator/v1/types_kubeapiserver.go index 71292438fb..d2c4ae04d7 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_kubeapiserver.go +++ b/vendor/github.com/openshift/api/operator/v1/types_kubeapiserver.go @@ -33,8 +33,8 @@ type KubeAPIServerStatus struct { // KubeAPIServerList is a collection of items type KubeAPIServerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []KubeAPIServer `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_kubecontrollermanager.go b/vendor/github.com/openshift/api/operator/v1/types_kubecontrollermanager.go index 664b3b6d7f..ee5c66cadb 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_kubecontrollermanager.go +++ b/vendor/github.com/openshift/api/operator/v1/types_kubecontrollermanager.go @@ -33,8 +33,8 @@ type KubeControllerManagerStatus struct { // KubeControllerManagerList is a collection of items type KubeControllerManagerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []KubeControllerManager `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_kubestorageversionmigrator.go b/vendor/github.com/openshift/api/operator/v1/types_kubestorageversionmigrator.go new file mode 100644 index 0000000000..5949ac021a --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1/types_kubestorageversionmigrator.go @@ -0,0 +1,40 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KubeStorageVersionMigrator provides information to configure an operator to manage kube-storage-version-migrator. +type KubeStorageVersionMigrator struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata"` + + // +kubebuilder:validation:Required + // +required + Spec KubeStorageVersionMigratorSpec `json:"spec"` + // +optional + Status KubeStorageVersionMigratorStatus `json:"status"` +} + +type KubeStorageVersionMigratorSpec struct { + OperatorSpec `json:",inline"` +} + +type KubeStorageVersionMigratorStatus struct { + OperatorStatus `json:",inline"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// KubeStorageVersionMigratorList is a collection of items +type KubeStorageVersionMigratorList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + // Items contains the items + Items []KubeStorageVersionMigrator `json:"items"` +} diff --git a/vendor/github.com/openshift/api/operator/v1/types_network.go b/vendor/github.com/openshift/api/operator/v1/types_network.go index d939df2bfc..a39b3c9a0e 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_network.go +++ b/vendor/github.com/openshift/api/operator/v1/types_network.go @@ -75,7 +75,7 @@ type NetworkSpec struct { // HostPrefix (in CIDR notation) will be allocated when nodes join the cluster. // Not all network providers support multiple ClusterNetworks type ClusterNetworkEntry struct { - CIDR string `json:"cidr"` + CIDR string `json:"cidr"` // +kubebuilder:validation:Minimum=0 HostPrefix uint32 `json:"hostPrefix"` } @@ -258,7 +258,7 @@ type KuryrConfig struct { OpenStackServiceNetwork string `json:"openStackServiceNetwork,omitempty"` } -// ovnKubernetesConfig is the proposed configuration parameters for networks +// ovnKubernetesConfig contains the configuration parameters for networks // using the ovn-kubernetes network project type OVNKubernetesConfig struct { // mtu is the MTU to use for the tunnel interface. This must be 100 @@ -267,6 +267,20 @@ type OVNKubernetesConfig struct { // +kubebuilder:validation:Minimum=0 // +optional MTU *uint32 `json:"mtu,omitempty"` + // geneve port is the UDP port to be used by geneve encapulation. + // Default is 6081 + // +kubebuilder:validation:Minimum=1 + // +optional + GenevePort *uint32 `json:"genevePort,omitempty"` + // HybridOverlayConfig configures an additional overlay network for peers that are + // not using OVN. + // +optional + HybridOverlayConfig *HybridOverlayConfig `json:"hybridOverlayConfig,omitempty"` +} + +type HybridOverlayConfig struct { + // HybridClusterNetwork defines a network space given to nodes on an additional overlay network. + HybridClusterNetwork []ClusterNetworkEntry `json:"hybridClusterNetwork"` } // NetworkType describes the network plugin type to configure diff --git a/vendor/github.com/openshift/api/operator/v1/types_openshiftapiserver.go b/vendor/github.com/openshift/api/operator/v1/types_openshiftapiserver.go index 63c552c7a8..16f9c3eedf 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_openshiftapiserver.go +++ b/vendor/github.com/openshift/api/operator/v1/types_openshiftapiserver.go @@ -33,8 +33,8 @@ type OpenShiftAPIServerStatus struct { // OpenShiftAPIServerList is a collection of items type OpenShiftAPIServerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []OpenShiftAPIServer `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_openshiftcontrollermanager.go b/vendor/github.com/openshift/api/operator/v1/types_openshiftcontrollermanager.go index 0d3f1e5c34..0f23b01be2 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_openshiftcontrollermanager.go +++ b/vendor/github.com/openshift/api/operator/v1/types_openshiftcontrollermanager.go @@ -33,8 +33,8 @@ type OpenShiftControllerManagerStatus struct { // OpenShiftControllerManagerList is a collection of items type OpenShiftControllerManagerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []OpenShiftControllerManager `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_scheduler.go b/vendor/github.com/openshift/api/operator/v1/types_scheduler.go index f9e4e74aca..20d5f759a5 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_scheduler.go +++ b/vendor/github.com/openshift/api/operator/v1/types_scheduler.go @@ -33,8 +33,8 @@ type KubeSchedulerStatus struct { // KubeSchedulerList is a collection of items type KubeSchedulerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []KubeScheduler `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_serviceca.go b/vendor/github.com/openshift/api/operator/v1/types_serviceca.go index 3859d9d5e6..b8d5e2646a 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_serviceca.go +++ b/vendor/github.com/openshift/api/operator/v1/types_serviceca.go @@ -35,8 +35,8 @@ type ServiceCAStatus struct { // ServiceCAList is a collection of items type ServiceCAList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []ServiceCA `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_servicecatalogapiserver.go b/vendor/github.com/openshift/api/operator/v1/types_servicecatalogapiserver.go index 5526b66f5b..7c1a857bb6 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_servicecatalogapiserver.go +++ b/vendor/github.com/openshift/api/operator/v1/types_servicecatalogapiserver.go @@ -33,8 +33,8 @@ type ServiceCatalogAPIServerStatus struct { // ServiceCatalogAPIServerList is a collection of items type ServiceCatalogAPIServerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []ServiceCatalogAPIServer `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/types_servicecatalogcontrollermanager.go b/vendor/github.com/openshift/api/operator/v1/types_servicecatalogcontrollermanager.go index 4378c0a3f1..ac3bf5898c 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_servicecatalogcontrollermanager.go +++ b/vendor/github.com/openshift/api/operator/v1/types_servicecatalogcontrollermanager.go @@ -33,8 +33,8 @@ type ServiceCatalogControllerManagerStatus struct { // ServiceCatalogControllerManagerList is a collection of items type ServiceCatalogControllerManagerList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` + // Items contains the items Items []ServiceCatalogControllerManager `json:"items"` } diff --git a/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go index 5ed29b74ad..647fc0b858 100644 --- a/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go @@ -5,6 +5,7 @@ package v1 import ( + configv1 "github.com/openshift/api/config/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" @@ -566,6 +567,27 @@ func (in *HostNetworkStrategy) DeepCopy() *HostNetworkStrategy { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HybridOverlayConfig) DeepCopyInto(out *HybridOverlayConfig) { + *out = *in + if in.HybridClusterNetwork != nil { + in, out := &in.HybridClusterNetwork, &out.HybridClusterNetwork + *out = make([]ClusterNetworkEntry, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HybridOverlayConfig. +func (in *HybridOverlayConfig) DeepCopy() *HybridOverlayConfig { + if in == nil { + return nil + } + out := new(HybridOverlayConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IPAMConfig) DeepCopyInto(out *IPAMConfig) { *out = *in @@ -681,6 +703,11 @@ func (in *IngressControllerSpec) DeepCopyInto(out *IngressControllerSpec) { *out = new(NodePlacement) (*in).DeepCopyInto(*out) } + if in.TLSSecurityProfile != nil { + in, out := &in.TLSSecurityProfile, &out.TLSSecurityProfile + *out = new(configv1.TLSSecurityProfile) + (*in).DeepCopyInto(*out) + } return } @@ -709,6 +736,11 @@ func (in *IngressControllerStatus) DeepCopyInto(out *IngressControllerStatus) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.TLSProfile != nil { + in, out := &in.TLSProfile, &out.TLSProfile + *out = new(configv1.TLSProfileSpec) + (*in).DeepCopyInto(*out) + } return } @@ -1007,6 +1039,101 @@ func (in *KubeSchedulerStatus) DeepCopy() *KubeSchedulerStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeStorageVersionMigrator) DeepCopyInto(out *KubeStorageVersionMigrator) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeStorageVersionMigrator. +func (in *KubeStorageVersionMigrator) DeepCopy() *KubeStorageVersionMigrator { + if in == nil { + return nil + } + out := new(KubeStorageVersionMigrator) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeStorageVersionMigrator) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeStorageVersionMigratorList) DeepCopyInto(out *KubeStorageVersionMigratorList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KubeStorageVersionMigrator, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeStorageVersionMigratorList. +func (in *KubeStorageVersionMigratorList) DeepCopy() *KubeStorageVersionMigratorList { + if in == nil { + return nil + } + out := new(KubeStorageVersionMigratorList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KubeStorageVersionMigratorList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeStorageVersionMigratorSpec) DeepCopyInto(out *KubeStorageVersionMigratorSpec) { + *out = *in + in.OperatorSpec.DeepCopyInto(&out.OperatorSpec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeStorageVersionMigratorSpec. +func (in *KubeStorageVersionMigratorSpec) DeepCopy() *KubeStorageVersionMigratorSpec { + if in == nil { + return nil + } + out := new(KubeStorageVersionMigratorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KubeStorageVersionMigratorStatus) DeepCopyInto(out *KubeStorageVersionMigratorStatus) { + *out = *in + in.OperatorStatus.DeepCopyInto(&out.OperatorStatus) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubeStorageVersionMigratorStatus. +func (in *KubeStorageVersionMigratorStatus) DeepCopy() *KubeStorageVersionMigratorStatus { + if in == nil { + return nil + } + out := new(KubeStorageVersionMigratorStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KuryrConfig) DeepCopyInto(out *KuryrConfig) { *out = *in @@ -1286,6 +1413,16 @@ func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = new(uint32) **out = **in } + if in.GenevePort != nil { + in, out := &in.GenevePort, &out.GenevePort + *out = new(uint32) + **out = **in + } + if in.HybridOverlayConfig != nil { + in, out := &in.HybridOverlayConfig, &out.HybridOverlayConfig + *out = new(HybridOverlayConfig) + (*in).DeepCopyInto(*out) + } return } diff --git a/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go index 57e40e8b17..91c6fb7aa7 100644 --- a/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go @@ -219,9 +219,8 @@ func (Etcd) SwaggerDoc() map[string]string { } var map_EtcdList = map[string]string{ - "": "KubeAPISOperatorConfigList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "KubeAPISOperatorConfigList is a collection of items", + "items": "Items contains the items", } func (EtcdList) SwaggerDoc() map[string]string { @@ -230,7 +229,7 @@ func (EtcdList) SwaggerDoc() map[string]string { var map_EndpointPublishingStrategy = map[string]string{ "": "EndpointPublishingStrategy is a way to publish the endpoints of an IngressController, and represents the type and any additional configuration for a specific type.", - "type": "type is the publishing strategy to use. Valid values are:\n\n* LoadBalancerService\n\nPublishes the ingress controller using a Kubernetes LoadBalancer Service.\n\nIn this configuration, the ingress controller deployment uses container networking. A LoadBalancer Service is created to publish the deployment.\n\nSee: https://kubernetes.io/docs/concepts/services-networking/#loadbalancer\n\nIf domain is set, a wildcard DNS record will be managed to point at the LoadBalancer Service's external name. DNS records are managed only in DNS zones defined by dns.config.openshift.io/cluster .spec.publicZone and .spec.privateZone.\n\nWildcard DNS management is currently supported only on the AWS, Azure, and GCP platforms.\n\n* HostNetwork\n\nPublishes the ingress controller on node ports where the ingress controller is deployed.\n\nIn this configuration, the ingress controller deployment uses host networking, bound to node ports 80 and 443. The user is responsible for configuring an external load balancer to publish the ingress controller via the node ports.\n\n* Private\n\nDoes not publish the ingress controller.\n\nIn this configuration, the ingress controller deployment uses container networking, and is not explicitly published. The user must manually publish the ingress controller.", + "type": "type is the publishing strategy to use. Valid values are:\n\n* LoadBalancerService\n\nPublishes the ingress controller using a Kubernetes LoadBalancer Service.\n\nIn this configuration, the ingress controller deployment uses container networking. A LoadBalancer Service is created to publish the deployment.\n\nSee: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer\n\nIf domain is set, a wildcard DNS record will be managed to point at the LoadBalancer Service's external name. DNS records are managed only in DNS zones defined by dns.config.openshift.io/cluster .spec.publicZone and .spec.privateZone.\n\nWildcard DNS management is currently supported only on the AWS, Azure, and GCP platforms.\n\n* HostNetwork\n\nPublishes the ingress controller on node ports where the ingress controller is deployed.\n\nIn this configuration, the ingress controller deployment uses host networking, bound to node ports 80 and 443. The user is responsible for configuring an external load balancer to publish the ingress controller via the node ports.\n\n* Private\n\nDoes not publish the ingress controller.\n\nIn this configuration, the ingress controller deployment uses container networking, and is not explicitly published. The user must manually publish the ingress controller.", "loadBalancer": "loadBalancer holds parameters for the load balancer. Present only if type is LoadBalancerService.", "hostNetwork": "hostNetwork holds parameters for the HostNetwork endpoint publishing strategy. Present only if type is HostNetwork.", "private": "private holds parameters for the Private endpoint publishing strategy. Present only if type is Private.", @@ -275,6 +274,7 @@ var map_IngressControllerSpec = map[string]string{ "namespaceSelector": "namespaceSelector is used to filter the set of namespaces serviced by the ingress controller. This is useful for implementing shards.\n\nIf unset, the default is no filtering.", "routeSelector": "routeSelector is used to filter the set of Routes serviced by the ingress controller. This is useful for implementing shards.\n\nIf unset, the default is no filtering.", "nodePlacement": "nodePlacement enables explicit control over the scheduling of the ingress controller.\n\nIf unset, defaults are used. See NodePlacement for more details.", + "tlsSecurityProfile": "tlsSecurityProfile specifies settings for TLS connections for ingresscontrollers.\n\nIf unset, the default is based on the apiservers.config.openshift.io/cluster resource.\n\nNote that when using the Old, Intermediate, and Modern profile types, the effective profile configuration is subject to change between releases. For example, given a specification to use the Intermediate profile deployed on release X.Y.Z, an upgrade to release X.Y.Z+1 may cause a new profile configuration to be applied to the ingress controller, resulting in a rollout.", } func (IngressControllerSpec) SwaggerDoc() map[string]string { @@ -288,6 +288,8 @@ var map_IngressControllerStatus = map[string]string{ "domain": "domain is the actual domain in use.", "endpointPublishingStrategy": "endpointPublishingStrategy is the actual strategy in use.", "conditions": "conditions is a list of conditions and their status.\n\nAvailable means the ingress controller deployment is available and servicing route and ingress resources (i.e, .status.availableReplicas equals .spec.replicas)\n\nThere are additional conditions which indicate the status of other ingress controller features and capabilities.\n\n * LoadBalancerManaged\n - True if the following conditions are met:\n * The endpoint publishing strategy requires a service load balancer.\n - False if any of those conditions are unsatisfied.\n\n * LoadBalancerReady\n - True if the following conditions are met:\n * A load balancer is managed.\n * The load balancer is ready.\n - False if any of those conditions are unsatisfied.\n\n * DNSManaged\n - True if the following conditions are met:\n * The endpoint publishing strategy and platform support DNS.\n * The ingress controller domain is set.\n * dns.config.openshift.io/cluster configures DNS zones.\n - False if any of those conditions are unsatisfied.\n\n * DNSReady\n - True if the following conditions are met:\n * DNS is managed.\n * DNS records have been successfully created.\n - False if any of those conditions are unsatisfied.", + "tlsProfile": "tlsProfile is the TLS connection configuration that is in effect.", + "observedGeneration": "observedGeneration is the most recent generation observed.", } func (IngressControllerStatus) SwaggerDoc() map[string]string { @@ -330,9 +332,8 @@ func (KubeAPIServer) SwaggerDoc() map[string]string { } var map_KubeAPIServerList = map[string]string{ - "": "KubeAPIServerList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "KubeAPIServerList is a collection of items", + "items": "Items contains the items", } func (KubeAPIServerList) SwaggerDoc() map[string]string { @@ -348,15 +349,31 @@ func (KubeControllerManager) SwaggerDoc() map[string]string { } var map_KubeControllerManagerList = map[string]string{ - "": "KubeControllerManagerList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "KubeControllerManagerList is a collection of items", + "items": "Items contains the items", } func (KubeControllerManagerList) SwaggerDoc() map[string]string { return map_KubeControllerManagerList } +var map_KubeStorageVersionMigrator = map[string]string{ + "": "KubeStorageVersionMigrator provides information to configure an operator to manage kube-storage-version-migrator.", +} + +func (KubeStorageVersionMigrator) SwaggerDoc() map[string]string { + return map_KubeStorageVersionMigrator +} + +var map_KubeStorageVersionMigratorList = map[string]string{ + "": "KubeStorageVersionMigratorList is a collection of items", + "items": "Items contains the items", +} + +func (KubeStorageVersionMigratorList) SwaggerDoc() map[string]string { + return map_KubeStorageVersionMigratorList +} + var map_AdditionalNetworkDefinition = map[string]string{ "": "AdditionalNetworkDefinition configures an extra network that is available but not created by default. Instead, pods must request them by name. type must be specified, along with exactly one \"Config\" that matches the type.", "type": "type is the type of network The supported values are NetworkTypeRaw, NetworkTypeSimpleMacvlan", @@ -390,6 +407,14 @@ func (DefaultNetworkDefinition) SwaggerDoc() map[string]string { return map_DefaultNetworkDefinition } +var map_HybridOverlayConfig = map[string]string{ + "hybridClusterNetwork": "HybridClusterNetwork defines a network space given to nodes on an additional overlay network.", +} + +func (HybridOverlayConfig) SwaggerDoc() map[string]string { + return map_HybridOverlayConfig +} + var map_IPAMConfig = map[string]string{ "": "IPAMConfig contains configurations for IPAM (IP Address Management)", "type": "Type is the type of IPAM module will be used for IP Address Management(IPAM). The supported values are IPAMTypeDHCP, IPAMTypeStatic", @@ -451,8 +476,10 @@ func (NetworkStatus) SwaggerDoc() map[string]string { } var map_OVNKubernetesConfig = map[string]string{ - "": "ovnKubernetesConfig is the proposed configuration parameters for networks using the ovn-kubernetes network project", - "mtu": "mtu is the MTU to use for the tunnel interface. This must be 100 bytes smaller than the uplink mtu. Default is 1400", + "": "ovnKubernetesConfig contains the configuration parameters for networks using the ovn-kubernetes network project", + "mtu": "mtu is the MTU to use for the tunnel interface. This must be 100 bytes smaller than the uplink mtu. Default is 1400", + "genevePort": "geneve port is the UDP port to be used by geneve encapulation. Default is 6081", + "hybridOverlayConfig": "HybridOverlayConfig configures an additional overlay network for peers that are not using OVN.", } func (OVNKubernetesConfig) SwaggerDoc() map[string]string { @@ -546,9 +573,8 @@ func (OpenShiftAPIServer) SwaggerDoc() map[string]string { } var map_OpenShiftAPIServerList = map[string]string{ - "": "OpenShiftAPIServerList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "OpenShiftAPIServerList is a collection of items", + "items": "Items contains the items", } func (OpenShiftAPIServerList) SwaggerDoc() map[string]string { @@ -564,9 +590,8 @@ func (OpenShiftControllerManager) SwaggerDoc() map[string]string { } var map_OpenShiftControllerManagerList = map[string]string{ - "": "OpenShiftControllerManagerList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "OpenShiftControllerManagerList is a collection of items", + "items": "Items contains the items", } func (OpenShiftControllerManagerList) SwaggerDoc() map[string]string { @@ -582,9 +607,8 @@ func (KubeScheduler) SwaggerDoc() map[string]string { } var map_KubeSchedulerList = map[string]string{ - "": "KubeSchedulerList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "KubeSchedulerList is a collection of items", + "items": "Items contains the items", } func (KubeSchedulerList) SwaggerDoc() map[string]string { @@ -602,9 +626,8 @@ func (ServiceCA) SwaggerDoc() map[string]string { } var map_ServiceCAList = map[string]string{ - "": "ServiceCAList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "ServiceCAList is a collection of items", + "items": "Items contains the items", } func (ServiceCAList) SwaggerDoc() map[string]string { @@ -620,9 +643,8 @@ func (ServiceCatalogAPIServer) SwaggerDoc() map[string]string { } var map_ServiceCatalogAPIServerList = map[string]string{ - "": "ServiceCatalogAPIServerList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "ServiceCatalogAPIServerList is a collection of items", + "items": "Items contains the items", } func (ServiceCatalogAPIServerList) SwaggerDoc() map[string]string { @@ -638,9 +660,8 @@ func (ServiceCatalogControllerManager) SwaggerDoc() map[string]string { } var map_ServiceCatalogControllerManagerList = map[string]string{ - "": "ServiceCatalogControllerManagerList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "ServiceCatalogControllerManagerList is a collection of items", + "items": "Items contains the items", } func (ServiceCatalogControllerManagerList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/operator/v1alpha1/0000_10_config-operator_01_imagecontentsourcepolicy.crd.yaml b/vendor/github.com/openshift/api/operator/v1alpha1/0000_10_config-operator_01_imagecontentsourcepolicy.crd.yaml new file mode 100644 index 0000000000..2c70eaa4f1 --- /dev/null +++ b/vendor/github.com/openshift/api/operator/v1alpha1/0000_10_config-operator_01_imagecontentsourcepolicy.crd.yaml @@ -0,0 +1,88 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: imagecontentsourcepolicies.operator.openshift.io +spec: + group: operator.openshift.io + scope: Cluster + preserveUnknownField: false + names: + kind: ImageContentSourcePolicy + singular: imagecontentsourcepolicy + plural: imagecontentsourcepolicies + listKind: ImageContentSourcePolicyList + versions: + - name: v1alpha1 + served: true + storage: true + subresources: + status: {} + "validation": + "openAPIV3Schema": + description: ImageContentSourcePolicy holds cluster-wide information about how + to handle registry mirror rules. When multiple policies are defined, the outcome + of the behavior is defined on each field. + type: object + required: + - spec + 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: + description: spec holds user settable values for configuration + type: object + properties: + repositoryDigestMirrors: + description: "repositoryDigestMirrors allows images referenced by image + digests in pods to be pulled from alternative mirrored repository + locations. The image pull specification provided to the pod will be + compared to the source locations described in RepositoryDigestMirrors + and the image may be pulled down from any of the mirrors in the list + instead of the specified repository allowing administrators to choose + a potentially faster mirror. Only image pull specifications that have + an image disgest will have this behavior applied to them - tags will + continue to be pulled from the specified repository in the pull spec. + \n Each “source” repository is treated independently; configurations + for different “source” repositories don’t interact. \n When multiple + policies are defined for the same “source” repository, the sets of + defined mirrors will be merged together, preserving the relative order + of the mirrors, if possible. For example, if policy A has mirrors + `a, b, c` and policy B has mirrors `c, d, e`, the mirrors will be + used in the order `a, b, c, d, e`. If the orders of mirror entries + conflict (e.g. `a, b` vs. `b, a`) the configuration is not rejected + but the resulting order is unspecified." + type: array + items: + description: 'RepositoryDigestMirrors holds cluster-wide information + about how to handle mirros in the registries config. Note: the mirrors + only work when pulling the images that are referenced by their digests.' + type: object + required: + - source + properties: + mirrors: + description: mirrors is one or more repositories that may also + contain the same images. The order of mirrors in this list is + treated as the user's desired priority, while source is by default + considered lower priority than all mirrors. Other cluster configuration, + including (but not limited to) other repositoryDigestMirrors + objects, may impact the exact order mirrors are contacted in, + or some mirrors may be contacted in parallel, so this should + be considered a preference rather than a guarantee of ordering. + type: array + items: + type: string + source: + description: source is the repository that users refer to, e.g. + in image pull specifications. + type: string diff --git a/vendor/github.com/openshift/api/operator/v1alpha1/types_image_content_source_policy.go b/vendor/github.com/openshift/api/operator/v1alpha1/types_image_content_source_policy.go index db5ec6ab15..49f8b95222 100644 --- a/vendor/github.com/openshift/api/operator/v1alpha1/types_image_content_source_policy.go +++ b/vendor/github.com/openshift/api/operator/v1alpha1/types_image_content_source_policy.go @@ -9,8 +9,7 @@ import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" // ImageContentSourcePolicy holds cluster-wide information about how to handle registry mirror rules. // When multiple policies are defined, the outcome of the behavior is defined on each field. type ImageContentSourcePolicy struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` // spec holds user settable values for configuration @@ -46,9 +45,9 @@ type ImageContentSourcePolicySpec struct { // ImageContentSourcePolicyList lists the items in the ImageContentSourcePolicy CRD. type ImageContentSourcePolicyList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata"` - Items []ImageContentSourcePolicy `json:"items"` + + Items []ImageContentSourcePolicy `json:"items"` } // RepositoryDigestMirrors holds cluster-wide information about how to handle mirros in the registries config. diff --git a/vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.swagger_doc_generated.go index 84d04215c7..5a32df8389 100644 --- a/vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/operator/v1alpha1/zz_generated.swagger_doc_generated.go @@ -136,9 +136,8 @@ func (VersionAvailability) SwaggerDoc() map[string]string { } var map_ImageContentSourcePolicy = map[string]string{ - "": "ImageContentSourcePolicy holds cluster-wide information about how to handle registry mirror rules. When multiple policies are defined, the outcome of the behavior is defined on each field.", - "metadata": "Standard object's metadata.", - "spec": "spec holds user settable values for configuration", + "": "ImageContentSourcePolicy holds cluster-wide information about how to handle registry mirror rules. When multiple policies are defined, the outcome of the behavior is defined on each field.", + "spec": "spec holds user settable values for configuration", } func (ImageContentSourcePolicy) SwaggerDoc() map[string]string { @@ -146,8 +145,7 @@ func (ImageContentSourcePolicy) SwaggerDoc() map[string]string { } var map_ImageContentSourcePolicyList = map[string]string{ - "": "ImageContentSourcePolicyList lists the items in the ImageContentSourcePolicy CRD.", - "metadata": "Standard object's metadata.", + "": "ImageContentSourcePolicyList lists the items in the ImageContentSourcePolicy CRD.", } func (ImageContentSourcePolicyList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/osin/v1/types.go b/vendor/github.com/openshift/api/osin/v1/types.go index e7d4f164c2..66f58b9e0c 100644 --- a/vendor/github.com/openshift/api/osin/v1/types.go +++ b/vendor/github.com/openshift/api/osin/v1/types.go @@ -105,6 +105,7 @@ type IdentityProvider struct { // mappingMethod determines how identities from this provider are mapped to users MappingMethod string `json:"mappingMethod"` // provider contains the information about how to set up a specific identity provider + // +kubebuilder:validation:PreserveUnknownFields Provider runtime.RawExtension `json:"provider"` } diff --git a/vendor/github.com/openshift/api/project/OWNERS b/vendor/github.com/openshift/api/project/OWNERS index ee74f4bc0f..9b1548f568 100644 --- a/vendor/github.com/openshift/api/project/OWNERS +++ b/vendor/github.com/openshift/api/project/OWNERS @@ -1,3 +1,2 @@ reviewers: - - enj - mfojtik diff --git a/vendor/github.com/openshift/api/project/v1/generated.proto b/vendor/github.com/openshift/api/project/v1/generated.proto index dec0f1e4b4..9624c47afb 100644 --- a/vendor/github.com/openshift/api/project/v1/generated.proto +++ b/vendor/github.com/openshift/api/project/v1/generated.proto @@ -25,7 +25,6 @@ option go_package = "v1"; // as editable to end users while namespaces are not. Direct creation of a project is typically restricted // to administrators, while end users should use the requestproject resource. message Project { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Spec defines the behavior of the Namespace. @@ -37,7 +36,6 @@ message Project { // ProjectList is a list of Project objects. message ProjectList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of projects @@ -46,7 +44,6 @@ message ProjectList { // ProjecRequest is the set of options necessary to fully qualify a project request message ProjectRequest { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // DisplayName is the display name to apply to a project diff --git a/vendor/github.com/openshift/api/project/v1/types.go b/vendor/github.com/openshift/api/project/v1/types.go index 51829507af..1c18dc5ef7 100644 --- a/vendor/github.com/openshift/api/project/v1/types.go +++ b/vendor/github.com/openshift/api/project/v1/types.go @@ -10,8 +10,8 @@ import ( // ProjectList is a list of Project objects. type ProjectList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of projects Items []Project `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -64,8 +64,7 @@ type ProjectStatus struct { // as editable to end users while namespaces are not. Direct creation of a project is typically restricted // to administrators, while end users should use the requestproject resource. type Project struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Spec defines the behavior of the Namespace. @@ -83,9 +82,9 @@ type Project struct { // ProjecRequest is the set of options necessary to fully qualify a project request type ProjectRequest struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // DisplayName is the display name to apply to a project DisplayName string `json:"displayName,omitempty" protobuf:"bytes,2,opt,name=displayName"` // Description is the description to apply to a project diff --git a/vendor/github.com/openshift/api/project/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/project/v1/zz_generated.swagger_doc_generated.go index 295892251a..080f2677ae 100644 --- a/vendor/github.com/openshift/api/project/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/project/v1/zz_generated.swagger_doc_generated.go @@ -12,10 +12,9 @@ package v1 // AUTO-GENERATED FUNCTIONS START HERE var map_Project = map[string]string{ - "": "Projects are the unit of isolation and collaboration in OpenShift. A project has one or more members, a quota on the resources that the project may consume, and the security controls on the resources in the project. Within a project, members may have different roles - project administrators can set membership, editors can create and manage the resources, and viewers can see but not access running containers. In a normal cluster project administrators are not able to alter their quotas - that is restricted to cluster administrators.\n\nListing or watching projects will return only projects the user has the reader role on.\n\nAn OpenShift project is an alternative representation of a Kubernetes namespace. Projects are exposed as editable to end users while namespaces are not. Direct creation of a project is typically restricted to administrators, while end users should use the requestproject resource.", - "metadata": "Standard object's metadata.", - "spec": "Spec defines the behavior of the Namespace.", - "status": "Status describes the current status of a Namespace", + "": "Projects are the unit of isolation and collaboration in OpenShift. A project has one or more members, a quota on the resources that the project may consume, and the security controls on the resources in the project. Within a project, members may have different roles - project administrators can set membership, editors can create and manage the resources, and viewers can see but not access running containers. In a normal cluster project administrators are not able to alter their quotas - that is restricted to cluster administrators.\n\nListing or watching projects will return only projects the user has the reader role on.\n\nAn OpenShift project is an alternative representation of a Kubernetes namespace. Projects are exposed as editable to end users while namespaces are not. Direct creation of a project is typically restricted to administrators, while end users should use the requestproject resource.", + "spec": "Spec defines the behavior of the Namespace.", + "status": "Status describes the current status of a Namespace", } func (Project) SwaggerDoc() map[string]string { @@ -23,9 +22,8 @@ func (Project) SwaggerDoc() map[string]string { } var map_ProjectList = map[string]string{ - "": "ProjectList is a list of Project objects.", - "metadata": "Standard object's metadata.", - "items": "Items is the list of projects", + "": "ProjectList is a list of Project objects.", + "items": "Items is the list of projects", } func (ProjectList) SwaggerDoc() map[string]string { @@ -34,7 +32,6 @@ func (ProjectList) SwaggerDoc() map[string]string { var map_ProjectRequest = map[string]string{ "": "ProjecRequest is the set of options necessary to fully qualify a project request", - "metadata": "Standard object's metadata.", "displayName": "DisplayName is the display name to apply to a project", "description": "Description is the description to apply to a project", } diff --git a/vendor/github.com/openshift/api/quota/v1/0000_03_quota-openshift_01_clusterresourcequota.crd.yaml b/vendor/github.com/openshift/api/quota/v1/0000_03_quota-openshift_01_clusterresourcequota.crd.yaml new file mode 100644 index 0000000000..d0e9e92b20 --- /dev/null +++ b/vendor/github.com/openshift/api/quota/v1/0000_03_quota-openshift_01_clusterresourcequota.crd.yaml @@ -0,0 +1,223 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: clusterresourcequotas.quota.openshift.io +spec: + group: quota.openshift.io + names: + kind: ClusterResourceQuota + listKind: ClusterResourceQuotaList + plural: clusterresourcequotas + singular: clusterresourcequota + preserveUnknownField: false + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: ClusterResourceQuota mirrors ResourceQuota at a cluster scope. This + object is easily convertible to synthetic ResourceQuota object to allow quota + evaluation re-use. + 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: + description: Spec defines the desired quota + properties: + quota: + description: Quota defines the desired quota + properties: + hard: + additionalProperties: + anyOf: + - type: string + - type: integer + type: string + description: 'hard is the set of desired hard limits for each named + resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/' + type: object + scopeSelector: + description: scopeSelector is also a collection of filters like + scopes that must match each object tracked by a quota but expressed + using ScopeSelectorOperator in combination with possible values. + For a resource to match, both scopes AND scopeSelector (if specified + in spec), must be matched. + properties: + matchExpressions: + description: A list of scope selector requirements by scope + of the resources. + items: + description: A scoped-resource selector requirement is a selector + that contains values, a scope name, and an operator that + relates the scope name and values. + properties: + operator: + description: Represents a scope's relationship to a set + of values. Valid operators are In, NotIn, Exists, DoesNotExist. + type: string + scopeName: + description: The name of the scope that the selector applies + to. + type: string + values: + description: An array of string values. If the operator + is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - operator + - scopeName + type: object + type: array + type: object + scopes: + description: A collection of filters that must match each object + tracked by a quota. If not specified, the quota matches all objects. + items: + description: A ResourceQuotaScope defines a filter that must match + each object tracked by a quota + type: string + type: array + type: object + selector: + description: Selector is the selector used to match projects. It should + only select active projects on the scale of dozens (though it can + select many more less active projects). These projects will contend + on object creation through this resource. + properties: + annotations: + additionalProperties: + type: string + description: AnnotationSelector is used to select projects by annotation. + nullable: true + type: object + labels: + description: LabelSelector is used to select projects by label. + nullable: true + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the + key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + type: object + required: + - quota + - selector + type: object + status: + description: Status defines the actual enforced quota and its current usage + properties: + namespaces: + description: Namespaces slices the usage by project. This division + allows for quick resolution of deletion reconciliation inside of a + single project without requiring a recalculation across all projects. This + can be used to pull the deltas for a given project. + items: + description: ResourceQuotaStatusByNamespace gives status for a particular + project + properties: + namespace: + description: Namespace the project this status applies to + type: string + status: + description: Status indicates how many resources have been consumed + by this project + properties: + hard: + additionalProperties: + type: string + description: 'Hard is the set of enforced hard limits for + each named resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/' + type: object + used: + additionalProperties: + type: string + description: Used is the current observed total usage of the + resource in the namespace. + type: object + type: object + required: + - namespace + - status + type: object + nullable: true + type: array + total: + description: Total defines the actual enforced quota and its current + usage across all projects + properties: + hard: + additionalProperties: + type: string + description: 'Hard is the set of enforced hard limits for each named + resource. More info: https://kubernetes.io/docs/concepts/policy/resource-quotas/' + type: object + used: + additionalProperties: + type: string + description: Used is the current observed total usage of the resource + in the namespace. + type: object + type: object + required: + - total + type: object + required: + - metadata + - spec + type: object + versions: + - name: v1 + served: true + storage: true diff --git a/vendor/github.com/openshift/api/quota/v1/0000_03_quota-openshift_01_clusterresourcequota.crd.yaml-merge-patch b/vendor/github.com/openshift/api/quota/v1/0000_03_quota-openshift_01_clusterresourcequota.crd.yaml-merge-patch new file mode 100644 index 0000000000..ffef0274f3 --- /dev/null +++ b/vendor/github.com/openshift/api/quota/v1/0000_03_quota-openshift_01_clusterresourcequota.crd.yaml-merge-patch @@ -0,0 +1,14 @@ +spec: + validation: + openAPIV3Schema: + properties: + spec: + properties: + quota: + properties: + hard: + additionalProperties: + anyOf: + - type: string + - type: integer + type: null diff --git a/vendor/github.com/openshift/api/quota/v1/generated.proto b/vendor/github.com/openshift/api/quota/v1/generated.proto index d651baf8a7..ba3fe4659d 100644 --- a/vendor/github.com/openshift/api/quota/v1/generated.proto +++ b/vendor/github.com/openshift/api/quota/v1/generated.proto @@ -16,7 +16,6 @@ option go_package = "v1"; // into a project. It allows a project-admin to know which ClusterResourceQuotas are applied to // his project and their associated usage. message AppliedClusterResourceQuota { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Spec defines the desired quota @@ -28,7 +27,6 @@ message AppliedClusterResourceQuota { // AppliedClusterResourceQuotaList is a collection of AppliedClusterResourceQuotas message AppliedClusterResourceQuotaList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of AppliedClusterResourceQuota @@ -38,7 +36,6 @@ message AppliedClusterResourceQuotaList { // ClusterResourceQuota mirrors ResourceQuota at a cluster scope. This object is easily convertible to // synthetic ResourceQuota object to allow quota evaluation re-use. message ClusterResourceQuota { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Spec defines the desired quota @@ -50,7 +47,6 @@ message ClusterResourceQuota { // ClusterResourceQuotaList is a collection of ClusterResourceQuotas message ClusterResourceQuotaList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of ClusterResourceQuotas diff --git a/vendor/github.com/openshift/api/quota/v1/types.go b/vendor/github.com/openshift/api/quota/v1/types.go index e34e815162..1bac842c7b 100644 --- a/vendor/github.com/openshift/api/quota/v1/types.go +++ b/vendor/github.com/openshift/api/quota/v1/types.go @@ -12,8 +12,7 @@ import ( // ClusterResourceQuota mirrors ResourceQuota at a cluster scope. This object is easily convertible to // synthetic ResourceQuota object to allow quota evaluation re-use. type ClusterResourceQuota struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"` // Spec defines the desired quota @@ -68,7 +67,6 @@ type ClusterResourceQuotaStatus struct { // ClusterResourceQuotaList is a collection of ClusterResourceQuotas type ClusterResourceQuotaList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of ClusterResourceQuotas @@ -95,8 +93,7 @@ type ResourceQuotaStatusByNamespace struct { // into a project. It allows a project-admin to know which ClusterResourceQuotas are applied to // his project and their associated usage. type AppliedClusterResourceQuota struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"` // Spec defines the desired quota @@ -111,7 +108,6 @@ type AppliedClusterResourceQuota struct { // AppliedClusterResourceQuotaList is a collection of AppliedClusterResourceQuotas type AppliedClusterResourceQuotaList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of AppliedClusterResourceQuota diff --git a/vendor/github.com/openshift/api/quota/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/quota/v1/zz_generated.swagger_doc_generated.go index d93479721c..71c0d6d56f 100644 --- a/vendor/github.com/openshift/api/quota/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/quota/v1/zz_generated.swagger_doc_generated.go @@ -12,10 +12,9 @@ package v1 // AUTO-GENERATED FUNCTIONS START HERE var map_AppliedClusterResourceQuota = map[string]string{ - "": "AppliedClusterResourceQuota mirrors ClusterResourceQuota at a project scope, for projection into a project. It allows a project-admin to know which ClusterResourceQuotas are applied to his project and their associated usage.", - "metadata": "Standard object's metadata.", - "spec": "Spec defines the desired quota", - "status": "Status defines the actual enforced quota and its current usage", + "": "AppliedClusterResourceQuota mirrors ClusterResourceQuota at a project scope, for projection into a project. It allows a project-admin to know which ClusterResourceQuotas are applied to his project and their associated usage.", + "spec": "Spec defines the desired quota", + "status": "Status defines the actual enforced quota and its current usage", } func (AppliedClusterResourceQuota) SwaggerDoc() map[string]string { @@ -23,9 +22,8 @@ func (AppliedClusterResourceQuota) SwaggerDoc() map[string]string { } var map_AppliedClusterResourceQuotaList = map[string]string{ - "": "AppliedClusterResourceQuotaList is a collection of AppliedClusterResourceQuotas", - "metadata": "Standard object's metadata.", - "items": "Items is a list of AppliedClusterResourceQuota", + "": "AppliedClusterResourceQuotaList is a collection of AppliedClusterResourceQuotas", + "items": "Items is a list of AppliedClusterResourceQuota", } func (AppliedClusterResourceQuotaList) SwaggerDoc() map[string]string { @@ -33,10 +31,9 @@ func (AppliedClusterResourceQuotaList) SwaggerDoc() map[string]string { } var map_ClusterResourceQuota = map[string]string{ - "": "ClusterResourceQuota mirrors ResourceQuota at a cluster scope. This object is easily convertible to synthetic ResourceQuota object to allow quota evaluation re-use.", - "metadata": "Standard object's metadata.", - "spec": "Spec defines the desired quota", - "status": "Status defines the actual enforced quota and its current usage", + "": "ClusterResourceQuota mirrors ResourceQuota at a cluster scope. This object is easily convertible to synthetic ResourceQuota object to allow quota evaluation re-use.", + "spec": "Spec defines the desired quota", + "status": "Status defines the actual enforced quota and its current usage", } func (ClusterResourceQuota) SwaggerDoc() map[string]string { @@ -44,9 +41,8 @@ func (ClusterResourceQuota) SwaggerDoc() map[string]string { } var map_ClusterResourceQuotaList = map[string]string{ - "": "ClusterResourceQuotaList is a collection of ClusterResourceQuotas", - "metadata": "Standard object's metadata.", - "items": "Items is a list of ClusterResourceQuotas", + "": "ClusterResourceQuotaList is a collection of ClusterResourceQuotas", + "items": "Items is a list of ClusterResourceQuotas", } func (ClusterResourceQuotaList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/route/v1/generated.proto b/vendor/github.com/openshift/api/route/v1/generated.proto index d4dfcdd628..5ede72545e 100644 --- a/vendor/github.com/openshift/api/route/v1/generated.proto +++ b/vendor/github.com/openshift/api/route/v1/generated.proto @@ -31,7 +31,6 @@ option go_package = "v1"; // If a client chooses a duplicate name, for instance, the route status conditions are used // to indicate the route cannot be chosen. message Route { - // Standard object metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // spec is the desired state of the route @@ -84,7 +83,6 @@ message RouteIngressCondition { // RouteList is a collection of Routes. message RouteList { - // Standard object metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // items is a list of routes diff --git a/vendor/github.com/openshift/api/route/v1/types.go b/vendor/github.com/openshift/api/route/v1/types.go index 4ea1881950..296b947abc 100644 --- a/vendor/github.com/openshift/api/route/v1/types.go +++ b/vendor/github.com/openshift/api/route/v1/types.go @@ -27,8 +27,7 @@ import ( // If a client chooses a duplicate name, for instance, the route status conditions are used // to indicate the route cannot be chosen. type Route struct { - metav1.TypeMeta `json:",inline"` - // Standard object metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // spec is the desired state of the route @@ -42,7 +41,6 @@ type Route struct { // RouteList is a collection of Routes. type RouteList struct { metav1.TypeMeta `json:",inline"` - // Standard object metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // items is a list of routes diff --git a/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go index d68df44981..c0fc24b653 100644 --- a/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go @@ -12,10 +12,9 @@ package v1 // AUTO-GENERATED FUNCTIONS START HERE var map_Route = map[string]string{ - "": "A route allows developers to expose services through an HTTP(S) aware load balancing and proxy layer via a public DNS entry. The route may further specify TLS options and a certificate, or specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An administrator typically configures their router to be visible outside the cluster firewall, and may also add additional security, caching, or traffic controls on the service content. Routers usually talk directly to the service endpoints.\n\nOnce a route is created, the `host` field may not be changed. Generally, routers use the oldest route with a given host when resolving conflicts.\n\nRouters are subject to additional customization and may support additional controls via the annotations field.\n\nBecause administrators may configure multiple routers, the route status field is used to return information to clients about the names and states of the route under each router. If a client chooses a duplicate name, for instance, the route status conditions are used to indicate the route cannot be chosen.", - "metadata": "Standard object metadata.", - "spec": "spec is the desired state of the route", - "status": "status is the current state of the route", + "": "A route allows developers to expose services through an HTTP(S) aware load balancing and proxy layer via a public DNS entry. The route may further specify TLS options and a certificate, or specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An administrator typically configures their router to be visible outside the cluster firewall, and may also add additional security, caching, or traffic controls on the service content. Routers usually talk directly to the service endpoints.\n\nOnce a route is created, the `host` field may not be changed. Generally, routers use the oldest route with a given host when resolving conflicts.\n\nRouters are subject to additional customization and may support additional controls via the annotations field.\n\nBecause administrators may configure multiple routers, the route status field is used to return information to clients about the names and states of the route under each router. If a client chooses a duplicate name, for instance, the route status conditions are used to indicate the route cannot be chosen.", + "spec": "spec is the desired state of the route", + "status": "status is the current state of the route", } func (Route) SwaggerDoc() map[string]string { @@ -49,9 +48,8 @@ func (RouteIngressCondition) SwaggerDoc() map[string]string { } var map_RouteList = map[string]string{ - "": "RouteList is a collection of Routes.", - "metadata": "Standard object metadata.", - "items": "items is a list of routes", + "": "RouteList is a collection of Routes.", + "items": "items is a list of routes", } func (RouteList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/security/OWNERS b/vendor/github.com/openshift/api/security/OWNERS deleted file mode 100644 index f0e98440ac..0000000000 --- a/vendor/github.com/openshift/api/security/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -reviewers: - - enj diff --git a/vendor/github.com/openshift/api/security/v1/0000_03_security-openshift_01_scc.crd.yaml b/vendor/github.com/openshift/api/security/v1/0000_03_security-openshift_01_scc.crd.yaml new file mode 100644 index 0000000000..025d995612 --- /dev/null +++ b/vendor/github.com/openshift/api/security/v1/0000_03_security-openshift_01_scc.crd.yaml @@ -0,0 +1,315 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: securitycontextconstraints.security.openshift.io +spec: + group: security.openshift.io + names: + kind: SecurityContextConstraints + listKind: SecurityContextConstraintsList + plural: securitycontextconstraints + singular: securitycontextconstraints + scope: Cluster + preserveUnknownField: false + versions: + - name: v1 + served: true + storage: true + "validation": + "openAPIV3Schema": + description: SecurityContextConstraints governs the ability to make requests + that affect the SecurityContext that will be applied to a container. For historical + reasons SCC was exposed under the core Kubernetes API group. That exposure + is deprecated and will be removed in a future release - users should instead + use the security.openshift.io group to manage SecurityContextConstraints. + type: object + required: + - allowHostDirVolumePlugin + - allowHostIPC + - allowHostNetwork + - allowHostPID + - allowHostPorts + - allowPrivilegedContainer + - allowedCapabilities + - defaultAddCapabilities + - priority + - readOnlyRootFilesystem + - requiredDropCapabilities + - volumes + properties: + allowHostDirVolumePlugin: + description: AllowHostDirVolumePlugin determines if the policy allow containers + to use the HostDir volume plugin + type: boolean + allowHostIPC: + description: AllowHostIPC determines if the policy allows host ipc in the + containers. + type: boolean + allowHostNetwork: + description: AllowHostNetwork determines if the policy allows the use of + HostNetwork in the pod spec. + type: boolean + allowHostPID: + description: AllowHostPID determines if the policy allows host pid in the + containers. + type: boolean + allowHostPorts: + description: AllowHostPorts determines if the policy allows host ports in + the containers. + type: boolean + allowPrivilegeEscalation: + description: AllowPrivilegeEscalation determines if a pod can request to + allow privilege escalation. If unspecified, defaults to true. + type: boolean + nullable: true + allowPrivilegedContainer: + description: AllowPrivilegedContainer determines if a container can request + to be run as privileged. + type: boolean + allowedCapabilities: + description: AllowedCapabilities is a list of capabilities that can be requested + to add to the container. Capabilities in this field maybe added at the + pod author's discretion. You must not list a capability in both AllowedCapabilities + and RequiredDropCapabilities. To allow all capabilities you may use '*'. + type: array + items: + description: Capability represent POSIX capabilities type + type: string + nullable: true + allowedFlexVolumes: + description: AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty + or nil indicates that all Flexvolumes may be used. This parameter is + effective only when the usage of the Flexvolumes is allowed in the "Volumes" + field. + type: array + items: + description: AllowedFlexVolume represents a single Flexvolume that is + allowed to be used. + type: object + required: + - driver + properties: + driver: + description: Driver is the name of the Flexvolume driver. + type: string + nullable: true + allowedUnsafeSysctls: + description: "AllowedUnsafeSysctls is a list of explicitly allowed unsafe + sysctls, defaults to none. Each entry is either a plain sysctl name or + ends in \"*\" in which case it is considered as a prefix of allowed sysctls. + Single * means all unsafe sysctls are allowed. Kubelet has to whitelist + all allowed unsafe sysctls explicitly to avoid rejection. \n Examples: + e.g. \"foo/*\" allows \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" allows + \"foo.bar\", \"foo.baz\", etc." + type: array + items: + type: string + nullable: true + 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 + defaultAddCapabilities: + description: DefaultAddCapabilities is the default set of capabilities that + will be added to the container unless the pod spec specifically drops + the capability. You may not list a capabiility in both DefaultAddCapabilities + and RequiredDropCapabilities. + type: array + items: + description: Capability represent POSIX capabilities type + type: string + nullable: true + defaultAllowPrivilegeEscalation: + description: DefaultAllowPrivilegeEscalation controls the default setting + for whether a process can gain more privileges than its parent process. + type: boolean + nullable: true + forbiddenSysctls: + description: "ForbiddenSysctls is a list of explicitly forbidden sysctls, + defaults to none. Each entry is either a plain sysctl name or ends in + \"*\" in which case it is considered as a prefix of forbidden sysctls. + Single * means all sysctls are forbidden. \n Examples: e.g. \"foo/*\" + forbids \"foo/bar\", \"foo/baz\", etc. e.g. \"foo.*\" forbids \"foo.bar\", + \"foo.baz\", etc." + type: array + items: + type: string + nullable: true + fsGroup: + description: FSGroup is the strategy that will dictate what fs group is + used by the SecurityContext. + type: object + properties: + ranges: + description: Ranges are the allowed ranges of fs groups. If you would + like to force a single fs group then supply a single range with the + same start and end. + type: array + items: + description: 'IDRange provides a min/max of an allowed range of IDs. + TODO: this could be reused for UIDs.' + type: object + properties: + max: + description: Max is the end of the range, inclusive. + type: integer + format: int64 + min: + description: Min is the start of the range, inclusive. + type: integer + format: int64 + type: + description: Type is the strategy that will dictate what FSGroup is + used in the SecurityContext. + type: string + nullable: true + groups: + description: The groups that have permission to use this security context + constraints + type: array + items: + type: string + nullable: true + 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 + priority: + description: Priority influences the sort order of SCCs when evaluating + which SCCs to try first for a given pod request based on access in the + Users and Groups fields. The higher the int, the higher priority. An + unset value is considered a 0 priority. If scores for multiple SCCs are + equal they will be sorted from most restrictive to least restrictive. + If both priorities and restrictions are equal the SCCs will be sorted + by name. + type: integer + format: int32 + nullable: true + readOnlyRootFilesystem: + description: ReadOnlyRootFilesystem when set to true will force containers + to run with a read only root file system. If the container specifically + requests to run with a non-read only root file system the SCC should deny + the pod. If set to false the container may run with a read only root file + system if it wishes but it will not be forced to. + type: boolean + requiredDropCapabilities: + description: RequiredDropCapabilities are the capabilities that will be + dropped from the container. These are required to be dropped and cannot + be added. + type: array + items: + description: Capability represent POSIX capabilities type + type: string + nullable: true + runAsUser: + description: RunAsUser is the strategy that will dictate what RunAsUser + is used in the SecurityContext. + type: object + properties: + type: + description: Type is the strategy that will dictate what RunAsUser is + used in the SecurityContext. + type: string + uid: + description: UID is the user id that containers must run as. Required + for the MustRunAs strategy if not using namespace/service account + allocated uids. + type: integer + format: int64 + uidRangeMax: + description: UIDRangeMax defines the max value for a strategy that allocates + by range. + type: integer + format: int64 + uidRangeMin: + description: UIDRangeMin defines the min value for a strategy that allocates + by range. + type: integer + format: int64 + nullable: true + seLinuxContext: + description: SELinuxContext is the strategy that will dictate what labels + will be set in the SecurityContext. + type: object + properties: + seLinuxOptions: + description: seLinuxOptions required to run as; required for MustRunAs + type: object + properties: + level: + description: Level is SELinux level label that applies to the container. + type: string + role: + description: Role is a SELinux role label that applies to the container. + type: string + type: + description: Type is a SELinux type label that applies to the container. + type: string + user: + description: User is a SELinux user label that applies to the container. + type: string + type: + description: Type is the strategy that will dictate what SELinux context + is used in the SecurityContext. + type: string + nullable: true + seccompProfiles: + description: "SeccompProfiles lists the allowed profiles that may be set + for the pod or container's seccomp annotations. An unset (nil) or empty + value means that no profiles may be specifid by the pod or container.\tThe + wildcard '*' may be used to allow all profiles. When used to generate + a value for a pod the first non-wildcard profile will be used as the default." + type: array + items: + type: string + nullable: true + supplementalGroups: + description: SupplementalGroups is the strategy that will dictate what supplemental + groups are used by the SecurityContext. + type: object + properties: + ranges: + description: Ranges are the allowed ranges of supplemental groups. If + you would like to force a single supplemental group then supply a + single range with the same start and end. + type: array + items: + description: 'IDRange provides a min/max of an allowed range of IDs. + TODO: this could be reused for UIDs.' + type: object + properties: + max: + description: Max is the end of the range, inclusive. + type: integer + format: int64 + min: + description: Min is the start of the range, inclusive. + type: integer + format: int64 + type: + description: Type is the strategy that will dictate what supplemental + groups is used in the SecurityContext. + type: string + nullable: true + users: + description: The users who have permissions to use this security context + constraints + type: array + items: + type: string + nullable: true + volumes: + description: Volumes is a white list of allowed volume plugins. FSType + corresponds directly with the field names of a VolumeSource (azureFile, + configMap, emptyDir). To allow all volumes you may use "*". To allow + no volumes, set to ["none"]. + type: array + items: + description: FS Type gives strong typing to different file systems that + are used by volumes. + type: string + nullable: true diff --git a/vendor/github.com/openshift/api/security/v1/generated.proto b/vendor/github.com/openshift/api/security/v1/generated.proto index 0a16d746f5..7cbba8eac0 100644 --- a/vendor/github.com/openshift/api/security/v1/generated.proto +++ b/vendor/github.com/openshift/api/security/v1/generated.proto @@ -125,9 +125,6 @@ message PodSecurityPolicySubjectReviewStatus { // RangeAllocation is used so we can easily expose a RangeAllocation typed for security group message RangeAllocation { - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // range is a string representing a unique label for a range of uids, "1000000000-2000000000/10000". @@ -140,7 +137,6 @@ message RangeAllocation { // RangeAllocationList is a list of RangeAllocations objects message RangeAllocationList { - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // List of RangeAllocations. @@ -180,8 +176,6 @@ message SELinuxContextStrategyOptions { // SecurityContextConstraints. // +kubebuilder:singular=securitycontextconstraint message SecurityContextConstraints { - // Standard object's metadata. - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Priority influences the sort order of SCCs when evaluating which SCCs to try first for @@ -322,7 +316,6 @@ message SecurityContextConstraints { // SecurityContextConstraintsList is a list of SecurityContextConstraints objects message SecurityContextConstraintsList { - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // List of security context constraints. diff --git a/vendor/github.com/openshift/api/security/v1/types.go b/vendor/github.com/openshift/api/security/v1/types.go index 2232a83dcb..5796a5f4e9 100644 --- a/vendor/github.com/openshift/api/security/v1/types.go +++ b/vendor/github.com/openshift/api/security/v1/types.go @@ -22,9 +22,7 @@ var AllowAllCapabilities corev1.Capability = "*" // SecurityContextConstraints. // +kubebuilder:singular=securitycontextconstraint type SecurityContextConstraints struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Priority influences the sort order of SCCs when evaluating which SCCs to try first for @@ -281,8 +279,6 @@ const ( // SecurityContextConstraintsList is a list of SecurityContextConstraints objects type SecurityContextConstraintsList struct { metav1.TypeMeta `json:",inline"` - - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // List of security context constraints. @@ -406,10 +402,7 @@ type ServiceAccountPodSecurityPolicyReviewStatus struct { // RangeAllocation is used so we can easily expose a RangeAllocation typed for security group type RangeAllocation struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. - // More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - // +optional + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // range is a string representing a unique label for a range of uids, "1000000000-2000000000/10000". @@ -425,8 +418,6 @@ type RangeAllocation struct { // RangeAllocationList is a list of RangeAllocations objects type RangeAllocationList struct { metav1.TypeMeta `json:",inline"` - - // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // List of RangeAllocations. diff --git a/vendor/github.com/openshift/api/security/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/security/v1/zz_generated.swagger_doc_generated.go index 60a167915e..1077c04017 100644 --- a/vendor/github.com/openshift/api/security/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/security/v1/zz_generated.swagger_doc_generated.go @@ -121,10 +121,9 @@ func (PodSecurityPolicySubjectReviewStatus) SwaggerDoc() map[string]string { } var map_RangeAllocation = map[string]string{ - "": "RangeAllocation is used so we can easily expose a RangeAllocation typed for security group", - "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", - "range": "range is a string representing a unique label for a range of uids, \"1000000000-2000000000/10000\".", - "data": "data is a byte array representing the serialized state of a range allocation. It is a bitmap with each bit set to one to represent a range is taken.", + "": "RangeAllocation is used so we can easily expose a RangeAllocation typed for security group", + "range": "range is a string representing a unique label for a range of uids, \"1000000000-2000000000/10000\".", + "data": "data is a byte array representing the serialized state of a range allocation. It is a bitmap with each bit set to one to represent a range is taken.", } func (RangeAllocation) SwaggerDoc() map[string]string { @@ -132,9 +131,8 @@ func (RangeAllocation) SwaggerDoc() map[string]string { } var map_RangeAllocationList = map[string]string{ - "": "RangeAllocationList is a list of RangeAllocations objects", - "metadata": "More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", - "items": "List of RangeAllocations.", + "": "RangeAllocationList is a list of RangeAllocations objects", + "items": "List of RangeAllocations.", } func (RangeAllocationList) SwaggerDoc() map[string]string { @@ -165,7 +163,6 @@ func (SELinuxContextStrategyOptions) SwaggerDoc() map[string]string { var map_SecurityContextConstraints = map[string]string{ "": "SecurityContextConstraints governs the ability to make requests that affect the SecurityContext that will be applied to a container. For historical reasons SCC was exposed under the core Kubernetes API group. That exposure is deprecated and will be removed in a future release - users should instead use the security.openshift.io group to manage SecurityContextConstraints.", - "metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", "priority": "Priority influences the sort order of SCCs when evaluating which SCCs to try first for a given pod request based on access in the Users and Groups fields. The higher the int, the higher priority. An unset value is considered a 0 priority. If scores for multiple SCCs are equal they will be sorted from most restrictive to least restrictive. If both priorities and restrictions are equal the SCCs will be sorted by name.", "allowPrivilegedContainer": "AllowPrivilegedContainer determines if a container can request to be run as privileged.", "defaultAddCapabilities": "DefaultAddCapabilities is the default set of capabilities that will be added to the container unless the pod spec specifically drops the capability. You may not list a capabiility in both DefaultAddCapabilities and RequiredDropCapabilities.", @@ -197,9 +194,8 @@ func (SecurityContextConstraints) SwaggerDoc() map[string]string { } var map_SecurityContextConstraintsList = map[string]string{ - "": "SecurityContextConstraintsList is a list of SecurityContextConstraints objects", - "metadata": "More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata", - "items": "List of security context constraints.", + "": "SecurityContextConstraintsList is a list of SecurityContextConstraints objects", + "items": "List of security context constraints.", } func (SecurityContextConstraintsList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/types.go b/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/types.go index 5ae4559108..37cc8c7915 100644 --- a/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/types.go +++ b/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/types.go @@ -76,18 +76,21 @@ type ServiceCertSignerOperatorConfigSpec struct { // it will end up overlaying in the following order: // 1. hardcoded default // 2. this config + // +kubebuilder:validation:PreserveUnknownFields ServiceServingCertSignerConfig runtime.RawExtension `json:"serviceServingCertSignerConfig"` // apiServiceCABundleInjectorConfig holds a sparse config that the user wants for this component. It only needs to be the overrides from the defaults // it will end up overlaying in the following order: // 1. hardcoded default // 2. this config + // +kubebuilder:validation:PreserveUnknownFields APIServiceCABundleInjectorConfig runtime.RawExtension `json:"apiServiceCABundleInjectorConfig"` // configMapCABundleInjectorConfig holds a sparse config that the user wants for this component. It only needs to be the overrides from the defaults // it will end up overlaying in the following order: // 1. hardcoded default // 2. this config + // +kubebuilder:validation:PreserveUnknownFields ConfigMapCABundleInjectorConfig runtime.RawExtension `json:"configMapCABundleInjectorConfig"` } @@ -100,8 +103,8 @@ type ServiceCertSignerOperatorConfigStatus struct { // ServiceCertSignerOperatorConfigList is a collection of items type ServiceCertSignerOperatorConfigList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty"` + // Items contains the items Items []ServiceCertSignerOperatorConfig `json:"items"` } diff --git a/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/zz_generated.swagger_doc_generated.go index 3401480cd8..6514f6f6c9 100644 --- a/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/servicecertsigner/v1alpha1/zz_generated.swagger_doc_generated.go @@ -38,9 +38,8 @@ func (ServiceCertSignerOperatorConfig) SwaggerDoc() map[string]string { } var map_ServiceCertSignerOperatorConfigList = map[string]string{ - "": "ServiceCertSignerOperatorConfigList is a collection of items", - "metadata": "Standard object's metadata.", - "items": "Items contains the items", + "": "ServiceCertSignerOperatorConfigList is a collection of items", + "items": "Items contains the items", } func (ServiceCertSignerOperatorConfigList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/template/v1/generated.proto b/vendor/github.com/openshift/api/template/v1/generated.proto index aa51f84127..49cc228c0d 100644 --- a/vendor/github.com/openshift/api/template/v1/generated.proto +++ b/vendor/github.com/openshift/api/template/v1/generated.proto @@ -16,7 +16,6 @@ option go_package = "v1"; // BrokerTemplateInstance holds the service broker-related state associated with // a TemplateInstance. BrokerTemplateInstance is part of an experimental API. message BrokerTemplateInstance { - // Standard object metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // spec describes the state of this BrokerTemplateInstance. @@ -25,7 +24,6 @@ message BrokerTemplateInstance { // BrokerTemplateInstanceList is a list of BrokerTemplateInstance objects. message BrokerTemplateInstanceList { - // Standard object metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // items is a list of BrokerTemplateInstances @@ -102,7 +100,6 @@ message Parameter { // Template contains the inputs needed to produce a Config. message Template { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // message is an optional instructional message that will @@ -119,6 +116,7 @@ message Template { // is, or contains, a ${PARAMETER_REFERENCE}, the resolved // value after parameter substitution will be respected and the object // will be created in that namespace. + // +kubebuilder:validation:PreserveUnknownFields repeated k8s.io.apimachinery.pkg.runtime.RawExtension objects = 3; // parameters is an optional array of Parameters used during the @@ -133,7 +131,6 @@ message Template { // TemplateInstance requests and records the instantiation of a Template. // TemplateInstance is part of an experimental API. message TemplateInstance { - // Standard object metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // spec describes the desired state of this TemplateInstance. @@ -167,7 +164,6 @@ message TemplateInstanceCondition { // TemplateInstanceList is a list of TemplateInstance objects. message TemplateInstanceList { - // Standard object metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // items is a list of Templateinstances @@ -226,7 +222,6 @@ message TemplateInstanceStatus { // TemplateList is a list of Template objects. message TemplateList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is a list of templates diff --git a/vendor/github.com/openshift/api/template/v1/types.go b/vendor/github.com/openshift/api/template/v1/types.go index a832c7c73d..1c71268064 100644 --- a/vendor/github.com/openshift/api/template/v1/types.go +++ b/vendor/github.com/openshift/api/template/v1/types.go @@ -13,8 +13,7 @@ import ( // Template contains the inputs needed to produce a Config. type Template struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // message is an optional instructional message that will @@ -31,6 +30,7 @@ type Template struct { // is, or contains, a ${PARAMETER_REFERENCE}, the resolved // value after parameter substitution will be respected and the object // will be created in that namespace. + // +kubebuilder:validation:PreserveUnknownFields Objects []runtime.RawExtension `json:"objects" protobuf:"bytes,3,rep,name=objects"` // parameters is an optional array of Parameters used during the @@ -47,7 +47,6 @@ type Template struct { // TemplateList is a list of Template objects. type TemplateList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Items is a list of templates @@ -105,8 +104,7 @@ type Parameter struct { // TemplateInstance requests and records the instantiation of a Template. // TemplateInstance is part of an experimental API. type TemplateInstance struct { - metav1.TypeMeta `json:",inline"` - // Standard object metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // spec describes the desired state of this TemplateInstance. @@ -211,7 +209,6 @@ type TemplateInstanceObject struct { // TemplateInstanceList is a list of TemplateInstance objects. type TemplateInstanceList struct { metav1.TypeMeta `json:",inline"` - // Standard object metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // items is a list of Templateinstances @@ -225,8 +222,7 @@ type TemplateInstanceList struct { // BrokerTemplateInstance holds the service broker-related state associated with // a TemplateInstance. BrokerTemplateInstance is part of an experimental API. type BrokerTemplateInstance struct { - metav1.TypeMeta `json:",inline"` - // Standard object metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // spec describes the state of this BrokerTemplateInstance. @@ -253,7 +249,6 @@ type BrokerTemplateInstanceSpec struct { // BrokerTemplateInstanceList is a list of BrokerTemplateInstance objects. type BrokerTemplateInstanceList struct { metav1.TypeMeta `json:",inline"` - // Standard object metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // items is a list of BrokerTemplateInstances diff --git a/vendor/github.com/openshift/api/template/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/template/v1/zz_generated.swagger_doc_generated.go index 001a477b4a..bbf8153101 100644 --- a/vendor/github.com/openshift/api/template/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/template/v1/zz_generated.swagger_doc_generated.go @@ -12,9 +12,8 @@ package v1 // AUTO-GENERATED FUNCTIONS START HERE var map_BrokerTemplateInstance = map[string]string{ - "": "BrokerTemplateInstance holds the service broker-related state associated with a TemplateInstance. BrokerTemplateInstance is part of an experimental API.", - "metadata": "Standard object metadata.", - "spec": "spec describes the state of this BrokerTemplateInstance.", + "": "BrokerTemplateInstance holds the service broker-related state associated with a TemplateInstance. BrokerTemplateInstance is part of an experimental API.", + "spec": "spec describes the state of this BrokerTemplateInstance.", } func (BrokerTemplateInstance) SwaggerDoc() map[string]string { @@ -22,9 +21,8 @@ func (BrokerTemplateInstance) SwaggerDoc() map[string]string { } var map_BrokerTemplateInstanceList = map[string]string{ - "": "BrokerTemplateInstanceList is a list of BrokerTemplateInstance objects.", - "metadata": "Standard object metadata.", - "items": "items is a list of BrokerTemplateInstances", + "": "BrokerTemplateInstanceList is a list of BrokerTemplateInstance objects.", + "items": "items is a list of BrokerTemplateInstances", } func (BrokerTemplateInstanceList) SwaggerDoc() map[string]string { @@ -59,7 +57,6 @@ func (Parameter) SwaggerDoc() map[string]string { var map_Template = map[string]string{ "": "Template contains the inputs needed to produce a Config.", - "metadata": "Standard object's metadata.", "message": "message is an optional instructional message that will be displayed when this template is instantiated. This field should inform the user how to utilize the newly created resources. Parameter substitution will be performed on the message before being displayed so that generated credentials and other parameters can be included in the output.", "objects": "objects is an array of resources to include in this template. If a namespace value is hardcoded in the object, it will be removed during template instantiation, however if the namespace value is, or contains, a ${PARAMETER_REFERENCE}, the resolved value after parameter substitution will be respected and the object will be created in that namespace.", "parameters": "parameters is an optional array of Parameters used during the Template to Config transformation.", @@ -71,10 +68,9 @@ func (Template) SwaggerDoc() map[string]string { } var map_TemplateInstance = map[string]string{ - "": "TemplateInstance requests and records the instantiation of a Template. TemplateInstance is part of an experimental API.", - "metadata": "Standard object metadata.", - "spec": "spec describes the desired state of this TemplateInstance.", - "status": "status describes the current state of this TemplateInstance.", + "": "TemplateInstance requests and records the instantiation of a Template. TemplateInstance is part of an experimental API.", + "spec": "spec describes the desired state of this TemplateInstance.", + "status": "status describes the current state of this TemplateInstance.", } func (TemplateInstance) SwaggerDoc() map[string]string { @@ -95,9 +91,8 @@ func (TemplateInstanceCondition) SwaggerDoc() map[string]string { } var map_TemplateInstanceList = map[string]string{ - "": "TemplateInstanceList is a list of TemplateInstance objects.", - "metadata": "Standard object metadata.", - "items": "items is a list of Templateinstances", + "": "TemplateInstanceList is a list of TemplateInstance objects.", + "items": "items is a list of Templateinstances", } func (TemplateInstanceList) SwaggerDoc() map[string]string { @@ -147,9 +142,8 @@ func (TemplateInstanceStatus) SwaggerDoc() map[string]string { } var map_TemplateList = map[string]string{ - "": "TemplateList is a list of Template objects.", - "metadata": "Standard object's metadata.", - "items": "Items is a list of templates", + "": "TemplateList is a list of Template objects.", + "items": "Items is a list of templates", } func (TemplateList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/user/OWNERS b/vendor/github.com/openshift/api/user/OWNERS deleted file mode 100644 index f0e98440ac..0000000000 --- a/vendor/github.com/openshift/api/user/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -reviewers: - - enj diff --git a/vendor/github.com/openshift/api/user/v1/generated.proto b/vendor/github.com/openshift/api/user/v1/generated.proto index 042e02a533..7444d41ef0 100644 --- a/vendor/github.com/openshift/api/user/v1/generated.proto +++ b/vendor/github.com/openshift/api/user/v1/generated.proto @@ -14,7 +14,6 @@ option go_package = "v1"; // Group represents a referenceable set of Users message Group { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Users is the list of users in this group. @@ -23,7 +22,6 @@ message Group { // GroupList is a collection of Groups message GroupList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of groups @@ -36,7 +34,6 @@ message GroupList { // user. Information retrieved from the authentication provider is stored in the extra field // using a schema determined by the provider. message Identity { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // ProviderName is the source of identity information @@ -55,7 +52,6 @@ message Identity { // IdentityList is a collection of Identities message IdentityList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of identities @@ -77,7 +73,6 @@ message OptionalNames { // identity provider - if a user already exists with the incoming name, the user name may have // a number appended to it depending on the configuration of the system. message User { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // FullName is the full name of user @@ -94,7 +89,6 @@ message User { // UserIdentityMapping maps a user to an identity message UserIdentityMapping { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1; // Identity is a reference to an identity @@ -106,7 +100,6 @@ message UserIdentityMapping { // UserList is a collection of Users message UserList { - // Standard object's metadata. optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1; // Items is the list of users diff --git a/vendor/github.com/openshift/api/user/v1/types.go b/vendor/github.com/openshift/api/user/v1/types.go index 6881b1728e..8708d02735 100644 --- a/vendor/github.com/openshift/api/user/v1/types.go +++ b/vendor/github.com/openshift/api/user/v1/types.go @@ -17,8 +17,7 @@ import ( // identity provider - if a user already exists with the incoming name, the user name may have // a number appended to it depending on the configuration of the system. type User struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // FullName is the full name of user @@ -38,8 +37,8 @@ type User struct { // UserList is a collection of Users type UserList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of users Items []User `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -54,8 +53,7 @@ type UserList struct { // user. Information retrieved from the authentication provider is stored in the extra field // using a schema determined by the provider. type Identity struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // ProviderName is the source of identity information @@ -77,8 +75,8 @@ type Identity struct { // IdentityList is a collection of Identities type IdentityList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of identities Items []Identity `json:"items" protobuf:"bytes,2,rep,name=items"` } @@ -90,8 +88,7 @@ type IdentityList struct { // UserIdentityMapping maps a user to an identity type UserIdentityMapping struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Identity is a reference to an identity @@ -115,8 +112,7 @@ func (t OptionalNames) String() string { // Group represents a referenceable set of Users type Group struct { - metav1.TypeMeta `json:",inline"` - // Standard object's metadata. + metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Users is the list of users in this group. @@ -128,8 +124,8 @@ type Group struct { // GroupList is a collection of Groups type GroupList struct { metav1.TypeMeta `json:",inline"` - // Standard object's metadata. metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + // Items is the list of groups Items []Group `json:"items" protobuf:"bytes,2,rep,name=items"` } diff --git a/vendor/github.com/openshift/api/user/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/user/v1/zz_generated.swagger_doc_generated.go index 0b30f12b83..e034251f96 100644 --- a/vendor/github.com/openshift/api/user/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/user/v1/zz_generated.swagger_doc_generated.go @@ -12,9 +12,8 @@ package v1 // AUTO-GENERATED FUNCTIONS START HERE var map_Group = map[string]string{ - "": "Group represents a referenceable set of Users", - "metadata": "Standard object's metadata.", - "users": "Users is the list of users in this group.", + "": "Group represents a referenceable set of Users", + "users": "Users is the list of users in this group.", } func (Group) SwaggerDoc() map[string]string { @@ -22,9 +21,8 @@ func (Group) SwaggerDoc() map[string]string { } var map_GroupList = map[string]string{ - "": "GroupList is a collection of Groups", - "metadata": "Standard object's metadata.", - "items": "Items is the list of groups", + "": "GroupList is a collection of Groups", + "items": "Items is the list of groups", } func (GroupList) SwaggerDoc() map[string]string { @@ -33,7 +31,6 @@ func (GroupList) SwaggerDoc() map[string]string { var map_Identity = map[string]string{ "": "Identity records a successful authentication of a user with an identity provider. The information about the source of authentication is stored on the identity, and the identity is then associated with a single user object. Multiple identities can reference a single user. Information retrieved from the authentication provider is stored in the extra field using a schema determined by the provider.", - "metadata": "Standard object's metadata.", "providerName": "ProviderName is the source of identity information", "providerUserName": "ProviderUserName uniquely represents this identity in the scope of the provider", "user": "User is a reference to the user this identity is associated with Both Name and UID must be set", @@ -45,9 +42,8 @@ func (Identity) SwaggerDoc() map[string]string { } var map_IdentityList = map[string]string{ - "": "IdentityList is a collection of Identities", - "metadata": "Standard object's metadata.", - "items": "Items is the list of identities", + "": "IdentityList is a collection of Identities", + "items": "Items is the list of identities", } func (IdentityList) SwaggerDoc() map[string]string { @@ -56,7 +52,6 @@ func (IdentityList) SwaggerDoc() map[string]string { var map_User = map[string]string{ "": "Upon log in, every user of the system receives a User and Identity resource. Administrators may directly manipulate the attributes of the users for their own tracking, or set groups via the API. The user name is unique and is chosen based on the value provided by the identity provider - if a user already exists with the incoming name, the user name may have a number appended to it depending on the configuration of the system.", - "metadata": "Standard object's metadata.", "fullName": "FullName is the full name of user", "identities": "Identities are the identities associated with this user", "groups": "Groups specifies group names this user is a member of. This field is deprecated and will be removed in a future release. Instead, create a Group object containing the name of this User.", @@ -68,7 +63,6 @@ func (User) SwaggerDoc() map[string]string { var map_UserIdentityMapping = map[string]string{ "": "UserIdentityMapping maps a user to an identity", - "metadata": "Standard object's metadata.", "identity": "Identity is a reference to an identity", "user": "User is a reference to a user", } @@ -78,9 +72,8 @@ func (UserIdentityMapping) SwaggerDoc() map[string]string { } var map_UserList = map[string]string{ - "": "UserList is a collection of Users", - "metadata": "Standard object's metadata.", - "items": "Items is the list of users", + "": "UserList is a collection of Users", + "items": "Items is the list of users", } func (UserList) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/webconsole/install.go b/vendor/github.com/openshift/api/webconsole/install.go deleted file mode 100644 index 645e5275e1..0000000000 --- a/vendor/github.com/openshift/api/webconsole/install.go +++ /dev/null @@ -1,26 +0,0 @@ -package webconsole - -import ( - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" - - webconsolev1 "github.com/openshift/api/webconsole/v1" -) - -const ( - GroupName = "webconsole.openshift.io" -) - -var ( - schemeBuilder = runtime.NewSchemeBuilder(webconsolev1.Install) - // Install is a function which adds every version of this group to a scheme - Install = schemeBuilder.AddToScheme -) - -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -func Kind(kind string) schema.GroupKind { - return schema.GroupKind{Group: GroupName, Kind: kind} -} diff --git a/vendor/github.com/openshift/api/webconsole/v1/doc.go b/vendor/github.com/openshift/api/webconsole/v1/doc.go deleted file mode 100644 index 1e2bcbd0cb..0000000000 --- a/vendor/github.com/openshift/api/webconsole/v1/doc.go +++ /dev/null @@ -1,8 +0,0 @@ -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/origin-web-console-server/pkg/apis/webconsole -// +k8s:defaulter-gen=TypeMeta -// +k8s:openapi-gen=true - -// +groupName=webconsole.config.openshift.io -// Package v1 is the v1 version of the API. -package v1 diff --git a/vendor/github.com/openshift/api/webconsole/v1/register.go b/vendor/github.com/openshift/api/webconsole/v1/register.go deleted file mode 100644 index de85ae1111..0000000000 --- a/vendor/github.com/openshift/api/webconsole/v1/register.go +++ /dev/null @@ -1,38 +0,0 @@ -package v1 - -import ( - configv1 "github.com/openshift/api/config/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -var ( - GroupName = "webconsole.config.openshift.io" - GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} - schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, configv1.Install) - // Install is a function which adds this version to a scheme - Install = schemeBuilder.AddToScheme - - // SchemeGroupVersion generated code relies on this name - // Deprecated - SchemeGroupVersion = GroupVersion - // AddToScheme exists solely to keep the old generators creating valid code - // DEPRECATED - AddToScheme = schemeBuilder.AddToScheme -) - -// Resource generated code relies on this being here, but it logically belongs to the group -// DEPRECATED -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{Group: GroupName, Resource: resource} -} - -// Adds the list of known types to api.Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(GroupVersion, - &WebConsoleConfiguration{}, - ) - metav1.AddToGroupVersion(scheme, GroupVersion) - return nil -} diff --git a/vendor/github.com/openshift/api/webconsole/v1/types.go b/vendor/github.com/openshift/api/webconsole/v1/types.go deleted file mode 100644 index 27a62e77f9..0000000000 --- a/vendor/github.com/openshift/api/webconsole/v1/types.go +++ /dev/null @@ -1,75 +0,0 @@ -package v1 - -import ( - configv1 "github.com/openshift/api/config/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// WebConsoleConfiguration holds the necessary configuration options for serving the web console -type WebConsoleConfiguration struct { - metav1.TypeMeta `json:",inline"` - - // ServingInfo is the HTTP serving information for these assets - ServingInfo configv1.HTTPServingInfo `json:"servingInfo"` - - // ClusterInfo holds information the web console needs to talk to the cluster such as master public URL - // and metrics public URL - ClusterInfo ClusterInfo `json:"clusterInfo"` - - // Features define various feature gates for the web console - Features FeaturesConfiguration `json:"features"` - - // Extensions define custom scripts, stylesheets, and properties used for web console customization - Extensions ExtensionsConfiguration `json:"extensions"` -} - -// ClusterInfo holds information the web console needs to talk to the cluster such as master public URL and -// metrics public URL -type ClusterInfo struct { - // ConsolePublicURL is where you can find the web console server (TODO do we really need this?) - ConsolePublicURL string `json:"consolePublicURL"` - - // MasterPublicURL is how the web console can access the OpenShift v1 server - MasterPublicURL string `json:"masterPublicURL"` - - // LoggingPublicURL is the public endpoint for logging (optional) - LoggingPublicURL string `json:"loggingPublicURL"` - - // MetricsPublicURL is the public endpoint for metrics (optional) - MetricsPublicURL string `json:"metricsPublicURL"` - - // LogoutPublicURL is an optional, absolute URL to redirect web browsers to after logging out of the web - // console. If not specified, the built-in logout page is shown. - LogoutPublicURL string `json:"logoutPublicURL"` - - // AdminConsolePublicURL is an optional, public URL of the OpenShift admin console. If specified, the web - // console will add a link to the admin console in a context selector in its masthead. - AdminConsolePublicURL string `json:"adminConsolePublicURL"` -} - -// FeaturesConfiguration defines various feature gates for the web console -type FeaturesConfiguration struct { - // InactivityTimeoutMinutes is the number of minutes of inactivity before you are automatically logged out of - // the web console (optional). If set to 0, inactivity timeout is disabled. - InactivityTimeoutMinutes int64 `json:"inactivityTimeoutMinutes"` - - // ClusterResourceOverridesEnabled indicates that the cluster is configured for overcommit. When set to - // true, the web console will hide the CPU request, CPU limit, and memory request fields in its editors - // and skip validation on those fields. The memory limit field will still be displayed. - ClusterResourceOverridesEnabled bool `json:"clusterResourceOverridesEnabled"` -} - -// ExtensionsConfiguration holds custom script, stylesheets, and properties used for web console customization -type ExtensionsConfiguration struct { - // ScriptURLs are URLs to load as scripts when the Web Console loads. The URLs must be accessible from - // the browser. - ScriptURLs []string `json:"scriptURLs"` - // StylesheetURLs are URLs to load as stylesheets when the Web Console loads. The URLs must be accessible - // from the browser. - StylesheetURLs []string `json:"stylesheetURLs"` - // Properties are key(string) and value(string) pairs that will be injected into the console under the - // global variable OPENSHIFT_EXTENSION_PROPERTIES - Properties map[string]string `json:"properties"` -} diff --git a/vendor/github.com/openshift/api/webconsole/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/webconsole/v1/zz_generated.deepcopy.go deleted file mode 100644 index c21658740b..0000000000 --- a/vendor/github.com/openshift/api/webconsole/v1/zz_generated.deepcopy.go +++ /dev/null @@ -1,103 +0,0 @@ -// +build !ignore_autogenerated - -// Code generated by deepcopy-gen. DO NOT EDIT. - -package v1 - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ClusterInfo) DeepCopyInto(out *ClusterInfo) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterInfo. -func (in *ClusterInfo) DeepCopy() *ClusterInfo { - if in == nil { - return nil - } - out := new(ClusterInfo) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExtensionsConfiguration) DeepCopyInto(out *ExtensionsConfiguration) { - *out = *in - if in.ScriptURLs != nil { - in, out := &in.ScriptURLs, &out.ScriptURLs - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.StylesheetURLs != nil { - in, out := &in.StylesheetURLs, &out.StylesheetURLs - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.Properties != nil { - in, out := &in.Properties, &out.Properties - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionsConfiguration. -func (in *ExtensionsConfiguration) DeepCopy() *ExtensionsConfiguration { - if in == nil { - return nil - } - out := new(ExtensionsConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *FeaturesConfiguration) DeepCopyInto(out *FeaturesConfiguration) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeaturesConfiguration. -func (in *FeaturesConfiguration) DeepCopy() *FeaturesConfiguration { - if in == nil { - return nil - } - out := new(FeaturesConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *WebConsoleConfiguration) DeepCopyInto(out *WebConsoleConfiguration) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ServingInfo.DeepCopyInto(&out.ServingInfo) - out.ClusterInfo = in.ClusterInfo - out.Features = in.Features - in.Extensions.DeepCopyInto(&out.Extensions) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebConsoleConfiguration. -func (in *WebConsoleConfiguration) DeepCopy() *WebConsoleConfiguration { - if in == nil { - return nil - } - out := new(WebConsoleConfiguration) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *WebConsoleConfiguration) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} diff --git a/vendor/github.com/openshift/api/webconsole/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/webconsole/v1/zz_generated.swagger_doc_generated.go deleted file mode 100644 index 9e96d0774c..0000000000 --- a/vendor/github.com/openshift/api/webconsole/v1/zz_generated.swagger_doc_generated.go +++ /dev/null @@ -1,61 +0,0 @@ -package v1 - -// This file contains a collection of methods that can be used from go-restful to -// generate Swagger API documentation for its models. Please read this PR for more -// information on the implementation: https://github.com/emicklei/go-restful/pull/215 -// -// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if -// they are on one line! For multiple line or blocks that you want to ignore use ---. -// Any context after a --- is ignored. -// -// Those methods can be generated by using hack/update-swagger-docs.sh - -// AUTO-GENERATED FUNCTIONS START HERE -var map_ClusterInfo = map[string]string{ - "": "ClusterInfo holds information the web console needs to talk to the cluster such as master public URL and metrics public URL", - "consolePublicURL": "ConsolePublicURL is where you can find the web console server (TODO do we really need this?)", - "masterPublicURL": "MasterPublicURL is how the web console can access the OpenShift v1 server", - "loggingPublicURL": "LoggingPublicURL is the public endpoint for logging (optional)", - "metricsPublicURL": "MetricsPublicURL is the public endpoint for metrics (optional)", - "logoutPublicURL": "LogoutPublicURL is an optional, absolute URL to redirect web browsers to after logging out of the web console. If not specified, the built-in logout page is shown.", - "adminConsolePublicURL": "AdminConsolePublicURL is an optional, public URL of the OpenShift admin console. If specified, the web console will add a link to the admin console in a context selector in its masthead.", -} - -func (ClusterInfo) SwaggerDoc() map[string]string { - return map_ClusterInfo -} - -var map_ExtensionsConfiguration = map[string]string{ - "": "ExtensionsConfiguration holds custom script, stylesheets, and properties used for web console customization", - "scriptURLs": "ScriptURLs are URLs to load as scripts when the Web Console loads. The URLs must be accessible from the browser.", - "stylesheetURLs": "StylesheetURLs are URLs to load as stylesheets when the Web Console loads. The URLs must be accessible from the browser.", - "properties": "Properties are key(string) and value(string) pairs that will be injected into the console under the global variable OPENSHIFT_EXTENSION_PROPERTIES", -} - -func (ExtensionsConfiguration) SwaggerDoc() map[string]string { - return map_ExtensionsConfiguration -} - -var map_FeaturesConfiguration = map[string]string{ - "": "FeaturesConfiguration defines various feature gates for the web console", - "inactivityTimeoutMinutes": "InactivityTimeoutMinutes is the number of minutes of inactivity before you are automatically logged out of the web console (optional). If set to 0, inactivity timeout is disabled.", - "clusterResourceOverridesEnabled": "ClusterResourceOverridesEnabled indicates that the cluster is configured for overcommit. When set to true, the web console will hide the CPU request, CPU limit, and memory request fields in its editors and skip validation on those fields. The memory limit field will still be displayed.", -} - -func (FeaturesConfiguration) SwaggerDoc() map[string]string { - return map_FeaturesConfiguration -} - -var map_WebConsoleConfiguration = map[string]string{ - "": "WebConsoleConfiguration holds the necessary configuration options for serving the web console", - "servingInfo": "ServingInfo is the HTTP serving information for these assets", - "clusterInfo": "ClusterInfo holds information the web console needs to talk to the cluster such as master public URL and metrics public URL", - "features": "Features define various feature gates for the web console", - "extensions": "Extensions define custom scripts, stylesheets, and properties used for web console customization", -} - -func (WebConsoleConfiguration) SwaggerDoc() map[string]string { - return map_WebConsoleConfiguration -} - -// AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/console_client.go b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/console_client.go index 4d6b5a70ba..11c82047ea 100644 --- a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/console_client.go +++ b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/console_client.go @@ -14,6 +14,7 @@ type ConsoleV1Interface interface { ConsoleExternalLogLinksGetter ConsoleLinksGetter ConsoleNotificationsGetter + ConsoleYAMLSamplesGetter } // ConsoleV1Client is used to interact with features provided by the console.openshift.io group. @@ -37,6 +38,10 @@ func (c *ConsoleV1Client) ConsoleNotifications() ConsoleNotificationInterface { return newConsoleNotifications(c) } +func (c *ConsoleV1Client) ConsoleYAMLSamples() ConsoleYAMLSampleInterface { + return newConsoleYAMLSamples(c) +} + // NewForConfig creates a new ConsoleV1Client for the given config. func NewForConfig(c *rest.Config) (*ConsoleV1Client, error) { config := *c diff --git a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/consoleyamlsample.go b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/consoleyamlsample.go new file mode 100644 index 0000000000..1802d28b4a --- /dev/null +++ b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/consoleyamlsample.go @@ -0,0 +1,148 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "time" + + v1 "github.com/openshift/api/console/v1" + scheme "github.com/openshift/client-go/console/clientset/versioned/scheme" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// ConsoleYAMLSamplesGetter has a method to return a ConsoleYAMLSampleInterface. +// A group's client should implement this interface. +type ConsoleYAMLSamplesGetter interface { + ConsoleYAMLSamples() ConsoleYAMLSampleInterface +} + +// ConsoleYAMLSampleInterface has methods to work with ConsoleYAMLSample resources. +type ConsoleYAMLSampleInterface interface { + Create(*v1.ConsoleYAMLSample) (*v1.ConsoleYAMLSample, error) + Update(*v1.ConsoleYAMLSample) (*v1.ConsoleYAMLSample, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.ConsoleYAMLSample, error) + List(opts metav1.ListOptions) (*v1.ConsoleYAMLSampleList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ConsoleYAMLSample, err error) + ConsoleYAMLSampleExpansion +} + +// consoleYAMLSamples implements ConsoleYAMLSampleInterface +type consoleYAMLSamples struct { + client rest.Interface +} + +// newConsoleYAMLSamples returns a ConsoleYAMLSamples +func newConsoleYAMLSamples(c *ConsoleV1Client) *consoleYAMLSamples { + return &consoleYAMLSamples{ + client: c.RESTClient(), + } +} + +// Get takes name of the consoleYAMLSample, and returns the corresponding consoleYAMLSample object, and an error if there is any. +func (c *consoleYAMLSamples) Get(name string, options metav1.GetOptions) (result *v1.ConsoleYAMLSample, err error) { + result = &v1.ConsoleYAMLSample{} + err = c.client.Get(). + Resource("consoleyamlsamples"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of ConsoleYAMLSamples that match those selectors. +func (c *consoleYAMLSamples) List(opts metav1.ListOptions) (result *v1.ConsoleYAMLSampleList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.ConsoleYAMLSampleList{} + err = c.client.Get(). + Resource("consoleyamlsamples"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested consoleYAMLSamples. +func (c *consoleYAMLSamples) Watch(opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("consoleyamlsamples"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a consoleYAMLSample and creates it. Returns the server's representation of the consoleYAMLSample, and an error, if there is any. +func (c *consoleYAMLSamples) Create(consoleYAMLSample *v1.ConsoleYAMLSample) (result *v1.ConsoleYAMLSample, err error) { + result = &v1.ConsoleYAMLSample{} + err = c.client.Post(). + Resource("consoleyamlsamples"). + Body(consoleYAMLSample). + Do(). + Into(result) + return +} + +// Update takes the representation of a consoleYAMLSample and updates it. Returns the server's representation of the consoleYAMLSample, and an error, if there is any. +func (c *consoleYAMLSamples) Update(consoleYAMLSample *v1.ConsoleYAMLSample) (result *v1.ConsoleYAMLSample, err error) { + result = &v1.ConsoleYAMLSample{} + err = c.client.Put(). + Resource("consoleyamlsamples"). + Name(consoleYAMLSample.Name). + Body(consoleYAMLSample). + Do(). + Into(result) + return +} + +// Delete takes name of the consoleYAMLSample and deletes it. Returns an error if one occurs. +func (c *consoleYAMLSamples) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Resource("consoleyamlsamples"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *consoleYAMLSamples) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("consoleyamlsamples"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched consoleYAMLSample. +func (c *consoleYAMLSamples) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ConsoleYAMLSample, err error) { + result = &v1.ConsoleYAMLSample{} + err = c.client.Patch(pt). + Resource("consoleyamlsamples"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/fake/fake_console_client.go b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/fake/fake_console_client.go index 84a3056040..7b06497711 100644 --- a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/fake/fake_console_client.go +++ b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/fake/fake_console_client.go @@ -28,6 +28,10 @@ func (c *FakeConsoleV1) ConsoleNotifications() v1.ConsoleNotificationInterface { return &FakeConsoleNotifications{c} } +func (c *FakeConsoleV1) ConsoleYAMLSamples() v1.ConsoleYAMLSampleInterface { + return &FakeConsoleYAMLSamples{c} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeConsoleV1) RESTClient() rest.Interface { diff --git a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/fake/fake_consoleyamlsample.go b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/fake/fake_consoleyamlsample.go new file mode 100644 index 0000000000..da3b0b9c5a --- /dev/null +++ b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/fake/fake_consoleyamlsample.go @@ -0,0 +1,104 @@ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + consolev1 "github.com/openshift/api/console/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeConsoleYAMLSamples implements ConsoleYAMLSampleInterface +type FakeConsoleYAMLSamples struct { + Fake *FakeConsoleV1 +} + +var consoleyamlsamplesResource = schema.GroupVersionResource{Group: "console.openshift.io", Version: "v1", Resource: "consoleyamlsamples"} + +var consoleyamlsamplesKind = schema.GroupVersionKind{Group: "console.openshift.io", Version: "v1", Kind: "ConsoleYAMLSample"} + +// Get takes name of the consoleYAMLSample, and returns the corresponding consoleYAMLSample object, and an error if there is any. +func (c *FakeConsoleYAMLSamples) Get(name string, options v1.GetOptions) (result *consolev1.ConsoleYAMLSample, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(consoleyamlsamplesResource, name), &consolev1.ConsoleYAMLSample{}) + if obj == nil { + return nil, err + } + return obj.(*consolev1.ConsoleYAMLSample), err +} + +// List takes label and field selectors, and returns the list of ConsoleYAMLSamples that match those selectors. +func (c *FakeConsoleYAMLSamples) List(opts v1.ListOptions) (result *consolev1.ConsoleYAMLSampleList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(consoleyamlsamplesResource, consoleyamlsamplesKind, opts), &consolev1.ConsoleYAMLSampleList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &consolev1.ConsoleYAMLSampleList{ListMeta: obj.(*consolev1.ConsoleYAMLSampleList).ListMeta} + for _, item := range obj.(*consolev1.ConsoleYAMLSampleList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested consoleYAMLSamples. +func (c *FakeConsoleYAMLSamples) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(consoleyamlsamplesResource, opts)) +} + +// Create takes the representation of a consoleYAMLSample and creates it. Returns the server's representation of the consoleYAMLSample, and an error, if there is any. +func (c *FakeConsoleYAMLSamples) Create(consoleYAMLSample *consolev1.ConsoleYAMLSample) (result *consolev1.ConsoleYAMLSample, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(consoleyamlsamplesResource, consoleYAMLSample), &consolev1.ConsoleYAMLSample{}) + if obj == nil { + return nil, err + } + return obj.(*consolev1.ConsoleYAMLSample), err +} + +// Update takes the representation of a consoleYAMLSample and updates it. Returns the server's representation of the consoleYAMLSample, and an error, if there is any. +func (c *FakeConsoleYAMLSamples) Update(consoleYAMLSample *consolev1.ConsoleYAMLSample) (result *consolev1.ConsoleYAMLSample, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(consoleyamlsamplesResource, consoleYAMLSample), &consolev1.ConsoleYAMLSample{}) + if obj == nil { + return nil, err + } + return obj.(*consolev1.ConsoleYAMLSample), err +} + +// Delete takes name of the consoleYAMLSample and deletes it. Returns an error if one occurs. +func (c *FakeConsoleYAMLSamples) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(consoleyamlsamplesResource, name), &consolev1.ConsoleYAMLSample{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeConsoleYAMLSamples) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(consoleyamlsamplesResource, listOptions) + + _, err := c.Fake.Invokes(action, &consolev1.ConsoleYAMLSampleList{}) + return err +} + +// Patch applies the patch and returns the patched consoleYAMLSample. +func (c *FakeConsoleYAMLSamples) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *consolev1.ConsoleYAMLSample, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(consoleyamlsamplesResource, name, pt, data, subresources...), &consolev1.ConsoleYAMLSample{}) + if obj == nil { + return nil, err + } + return obj.(*consolev1.ConsoleYAMLSample), err +} diff --git a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/generated_expansion.go b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/generated_expansion.go index ce55c4b5c6..be930d5148 100644 --- a/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/generated_expansion.go +++ b/vendor/github.com/openshift/client-go/console/clientset/versioned/typed/console/v1/generated_expansion.go @@ -9,3 +9,5 @@ type ConsoleExternalLogLinkExpansion interface{} type ConsoleLinkExpansion interface{} type ConsoleNotificationExpansion interface{} + +type ConsoleYAMLSampleExpansion interface{} diff --git a/vendor/github.com/openshift/client-go/console/informers/externalversions/console/v1/consoleyamlsample.go b/vendor/github.com/openshift/client-go/console/informers/externalversions/console/v1/consoleyamlsample.go new file mode 100644 index 0000000000..c9b74bee22 --- /dev/null +++ b/vendor/github.com/openshift/client-go/console/informers/externalversions/console/v1/consoleyamlsample.go @@ -0,0 +1,72 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + time "time" + + consolev1 "github.com/openshift/api/console/v1" + versioned "github.com/openshift/client-go/console/clientset/versioned" + internalinterfaces "github.com/openshift/client-go/console/informers/externalversions/internalinterfaces" + v1 "github.com/openshift/client-go/console/listers/console/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// ConsoleYAMLSampleInformer provides access to a shared informer and lister for +// ConsoleYAMLSamples. +type ConsoleYAMLSampleInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.ConsoleYAMLSampleLister +} + +type consoleYAMLSampleInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewConsoleYAMLSampleInformer constructs a new informer for ConsoleYAMLSample type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewConsoleYAMLSampleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredConsoleYAMLSampleInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredConsoleYAMLSampleInformer constructs a new informer for ConsoleYAMLSample type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredConsoleYAMLSampleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ConsoleV1().ConsoleYAMLSamples().List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.ConsoleV1().ConsoleYAMLSamples().Watch(options) + }, + }, + &consolev1.ConsoleYAMLSample{}, + resyncPeriod, + indexers, + ) +} + +func (f *consoleYAMLSampleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredConsoleYAMLSampleInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *consoleYAMLSampleInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&consolev1.ConsoleYAMLSample{}, f.defaultInformer) +} + +func (f *consoleYAMLSampleInformer) Lister() v1.ConsoleYAMLSampleLister { + return v1.NewConsoleYAMLSampleLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/openshift/client-go/console/informers/externalversions/console/v1/interface.go b/vendor/github.com/openshift/client-go/console/informers/externalversions/console/v1/interface.go index 1e4944cd21..4e45f1e2a2 100644 --- a/vendor/github.com/openshift/client-go/console/informers/externalversions/console/v1/interface.go +++ b/vendor/github.com/openshift/client-go/console/informers/externalversions/console/v1/interface.go @@ -16,6 +16,8 @@ type Interface interface { ConsoleLinks() ConsoleLinkInformer // ConsoleNotifications returns a ConsoleNotificationInformer. ConsoleNotifications() ConsoleNotificationInformer + // ConsoleYAMLSamples returns a ConsoleYAMLSampleInformer. + ConsoleYAMLSamples() ConsoleYAMLSampleInformer } type version struct { @@ -48,3 +50,8 @@ func (v *version) ConsoleLinks() ConsoleLinkInformer { func (v *version) ConsoleNotifications() ConsoleNotificationInformer { return &consoleNotificationInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } + +// ConsoleYAMLSamples returns a ConsoleYAMLSampleInformer. +func (v *version) ConsoleYAMLSamples() ConsoleYAMLSampleInformer { + return &consoleYAMLSampleInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} diff --git a/vendor/github.com/openshift/client-go/console/informers/externalversions/generic.go b/vendor/github.com/openshift/client-go/console/informers/externalversions/generic.go index 345c3a224f..818ee394e4 100644 --- a/vendor/github.com/openshift/client-go/console/informers/externalversions/generic.go +++ b/vendor/github.com/openshift/client-go/console/informers/externalversions/generic.go @@ -45,6 +45,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Console().V1().ConsoleLinks().Informer()}, nil case v1.SchemeGroupVersion.WithResource("consolenotifications"): return &genericInformer{resource: resource.GroupResource(), informer: f.Console().V1().ConsoleNotifications().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("consoleyamlsamples"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Console().V1().ConsoleYAMLSamples().Informer()}, nil } diff --git a/vendor/github.com/openshift/client-go/console/listers/console/v1/consoleyamlsample.go b/vendor/github.com/openshift/client-go/console/listers/console/v1/consoleyamlsample.go new file mode 100644 index 0000000000..cbed2f7a23 --- /dev/null +++ b/vendor/github.com/openshift/client-go/console/listers/console/v1/consoleyamlsample.go @@ -0,0 +1,49 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/openshift/api/console/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// ConsoleYAMLSampleLister helps list ConsoleYAMLSamples. +type ConsoleYAMLSampleLister interface { + // List lists all ConsoleYAMLSamples in the indexer. + List(selector labels.Selector) (ret []*v1.ConsoleYAMLSample, err error) + // Get retrieves the ConsoleYAMLSample from the index for a given name. + Get(name string) (*v1.ConsoleYAMLSample, error) + ConsoleYAMLSampleListerExpansion +} + +// consoleYAMLSampleLister implements the ConsoleYAMLSampleLister interface. +type consoleYAMLSampleLister struct { + indexer cache.Indexer +} + +// NewConsoleYAMLSampleLister returns a new ConsoleYAMLSampleLister. +func NewConsoleYAMLSampleLister(indexer cache.Indexer) ConsoleYAMLSampleLister { + return &consoleYAMLSampleLister{indexer: indexer} +} + +// List lists all ConsoleYAMLSamples in the indexer. +func (s *consoleYAMLSampleLister) List(selector labels.Selector) (ret []*v1.ConsoleYAMLSample, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.ConsoleYAMLSample)) + }) + return ret, err +} + +// Get retrieves the ConsoleYAMLSample from the index for a given name. +func (s *consoleYAMLSampleLister) Get(name string) (*v1.ConsoleYAMLSample, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("consoleyamlsample"), name) + } + return obj.(*v1.ConsoleYAMLSample), nil +} diff --git a/vendor/github.com/openshift/client-go/console/listers/console/v1/expansion_generated.go b/vendor/github.com/openshift/client-go/console/listers/console/v1/expansion_generated.go index a7fd2b6b41..694b0ba152 100644 --- a/vendor/github.com/openshift/client-go/console/listers/console/v1/expansion_generated.go +++ b/vendor/github.com/openshift/client-go/console/listers/console/v1/expansion_generated.go @@ -17,3 +17,7 @@ type ConsoleLinkListerExpansion interface{} // ConsoleNotificationListerExpansion allows custom methods to be added to // ConsoleNotificationLister. type ConsoleNotificationListerExpansion interface{} + +// ConsoleYAMLSampleListerExpansion allows custom methods to be added to +// ConsoleYAMLSampleLister. +type ConsoleYAMLSampleListerExpansion interface{} diff --git a/vendor/github.com/openshift/client-go/glide.lock b/vendor/github.com/openshift/client-go/glide.lock index 70f2e978b2..1a9a75e46f 100644 --- a/vendor/github.com/openshift/client-go/glide.lock +++ b/vendor/github.com/openshift/client-go/glide.lock @@ -1,5 +1,5 @@ hash: 2663fb491e5aaae0ef7675336a7de1c726825ead2b386719b9b4cb3471a12ad9 -updated: 2019-09-23T13:54:27.435274936-04:00 +updated: 2019-10-21T15:20:05.249062391-04:00 imports: - name: github.com/davecgh/go-spew version: 8991bc29aa16c548c550c7ff78260e27b9ab7c73 @@ -49,12 +49,13 @@ imports: - name: github.com/modern-go/reflect2 version: 94122c33edd36123c84d5368cfb2b69df93a0ec8 - name: github.com/openshift/api - version: ecbc01928def629f4422dcbcc3362efddfc513ee + version: c95b469ab84f449b0e4644c6ee2b9e5e9d8c2b13 subpackages: - apps/v1 - authorization/v1 - build/v1 - config/v1 + - console/v1 - image/docker10 - image/dockerpre012 - image/v1 diff --git a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/fake/fake_kubestorageversionmigrator.go b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/fake/fake_kubestorageversionmigrator.go new file mode 100644 index 0000000000..e0d316b11d --- /dev/null +++ b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/fake/fake_kubestorageversionmigrator.go @@ -0,0 +1,115 @@ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + operatorv1 "github.com/openshift/api/operator/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeKubeStorageVersionMigrators implements KubeStorageVersionMigratorInterface +type FakeKubeStorageVersionMigrators struct { + Fake *FakeOperatorV1 +} + +var kubestorageversionmigratorsResource = schema.GroupVersionResource{Group: "operator.openshift.io", Version: "v1", Resource: "kubestorageversionmigrators"} + +var kubestorageversionmigratorsKind = schema.GroupVersionKind{Group: "operator.openshift.io", Version: "v1", Kind: "KubeStorageVersionMigrator"} + +// Get takes name of the kubeStorageVersionMigrator, and returns the corresponding kubeStorageVersionMigrator object, and an error if there is any. +func (c *FakeKubeStorageVersionMigrators) Get(name string, options v1.GetOptions) (result *operatorv1.KubeStorageVersionMigrator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(kubestorageversionmigratorsResource, name), &operatorv1.KubeStorageVersionMigrator{}) + if obj == nil { + return nil, err + } + return obj.(*operatorv1.KubeStorageVersionMigrator), err +} + +// List takes label and field selectors, and returns the list of KubeStorageVersionMigrators that match those selectors. +func (c *FakeKubeStorageVersionMigrators) List(opts v1.ListOptions) (result *operatorv1.KubeStorageVersionMigratorList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(kubestorageversionmigratorsResource, kubestorageversionmigratorsKind, opts), &operatorv1.KubeStorageVersionMigratorList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &operatorv1.KubeStorageVersionMigratorList{ListMeta: obj.(*operatorv1.KubeStorageVersionMigratorList).ListMeta} + for _, item := range obj.(*operatorv1.KubeStorageVersionMigratorList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested kubeStorageVersionMigrators. +func (c *FakeKubeStorageVersionMigrators) Watch(opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(kubestorageversionmigratorsResource, opts)) +} + +// Create takes the representation of a kubeStorageVersionMigrator and creates it. Returns the server's representation of the kubeStorageVersionMigrator, and an error, if there is any. +func (c *FakeKubeStorageVersionMigrators) Create(kubeStorageVersionMigrator *operatorv1.KubeStorageVersionMigrator) (result *operatorv1.KubeStorageVersionMigrator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(kubestorageversionmigratorsResource, kubeStorageVersionMigrator), &operatorv1.KubeStorageVersionMigrator{}) + if obj == nil { + return nil, err + } + return obj.(*operatorv1.KubeStorageVersionMigrator), err +} + +// Update takes the representation of a kubeStorageVersionMigrator and updates it. Returns the server's representation of the kubeStorageVersionMigrator, and an error, if there is any. +func (c *FakeKubeStorageVersionMigrators) Update(kubeStorageVersionMigrator *operatorv1.KubeStorageVersionMigrator) (result *operatorv1.KubeStorageVersionMigrator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(kubestorageversionmigratorsResource, kubeStorageVersionMigrator), &operatorv1.KubeStorageVersionMigrator{}) + if obj == nil { + return nil, err + } + return obj.(*operatorv1.KubeStorageVersionMigrator), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeKubeStorageVersionMigrators) UpdateStatus(kubeStorageVersionMigrator *operatorv1.KubeStorageVersionMigrator) (*operatorv1.KubeStorageVersionMigrator, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(kubestorageversionmigratorsResource, "status", kubeStorageVersionMigrator), &operatorv1.KubeStorageVersionMigrator{}) + if obj == nil { + return nil, err + } + return obj.(*operatorv1.KubeStorageVersionMigrator), err +} + +// Delete takes name of the kubeStorageVersionMigrator and deletes it. Returns an error if one occurs. +func (c *FakeKubeStorageVersionMigrators) Delete(name string, options *v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(kubestorageversionmigratorsResource, name), &operatorv1.KubeStorageVersionMigrator{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeKubeStorageVersionMigrators) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(kubestorageversionmigratorsResource, listOptions) + + _, err := c.Fake.Invokes(action, &operatorv1.KubeStorageVersionMigratorList{}) + return err +} + +// Patch applies the patch and returns the patched kubeStorageVersionMigrator. +func (c *FakeKubeStorageVersionMigrators) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *operatorv1.KubeStorageVersionMigrator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(kubestorageversionmigratorsResource, name, pt, data, subresources...), &operatorv1.KubeStorageVersionMigrator{}) + if obj == nil { + return nil, err + } + return obj.(*operatorv1.KubeStorageVersionMigrator), err +} diff --git a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/fake/fake_operator_client.go b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/fake/fake_operator_client.go index 48597525e6..b2dc3b3703 100644 --- a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/fake/fake_operator_client.go +++ b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/fake/fake_operator_client.go @@ -44,6 +44,10 @@ func (c *FakeOperatorV1) KubeSchedulers() v1.KubeSchedulerInterface { return &FakeKubeSchedulers{c} } +func (c *FakeOperatorV1) KubeStorageVersionMigrators() v1.KubeStorageVersionMigratorInterface { + return &FakeKubeStorageVersionMigrators{c} +} + func (c *FakeOperatorV1) Networks() v1.NetworkInterface { return &FakeNetworks{c} } diff --git a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/generated_expansion.go b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/generated_expansion.go index ed3ef55e35..18807b6ff2 100644 --- a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/generated_expansion.go +++ b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/generated_expansion.go @@ -18,6 +18,8 @@ type KubeControllerManagerExpansion interface{} type KubeSchedulerExpansion interface{} +type KubeStorageVersionMigratorExpansion interface{} + type NetworkExpansion interface{} type OpenShiftAPIServerExpansion interface{} diff --git a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/kubestorageversionmigrator.go b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/kubestorageversionmigrator.go new file mode 100644 index 0000000000..0dff019f08 --- /dev/null +++ b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/kubestorageversionmigrator.go @@ -0,0 +1,164 @@ +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "time" + + v1 "github.com/openshift/api/operator/v1" + scheme "github.com/openshift/client-go/operator/clientset/versioned/scheme" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// KubeStorageVersionMigratorsGetter has a method to return a KubeStorageVersionMigratorInterface. +// A group's client should implement this interface. +type KubeStorageVersionMigratorsGetter interface { + KubeStorageVersionMigrators() KubeStorageVersionMigratorInterface +} + +// KubeStorageVersionMigratorInterface has methods to work with KubeStorageVersionMigrator resources. +type KubeStorageVersionMigratorInterface interface { + Create(*v1.KubeStorageVersionMigrator) (*v1.KubeStorageVersionMigrator, error) + Update(*v1.KubeStorageVersionMigrator) (*v1.KubeStorageVersionMigrator, error) + UpdateStatus(*v1.KubeStorageVersionMigrator) (*v1.KubeStorageVersionMigrator, error) + Delete(name string, options *metav1.DeleteOptions) error + DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error + Get(name string, options metav1.GetOptions) (*v1.KubeStorageVersionMigrator, error) + List(opts metav1.ListOptions) (*v1.KubeStorageVersionMigratorList, error) + Watch(opts metav1.ListOptions) (watch.Interface, error) + Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.KubeStorageVersionMigrator, err error) + KubeStorageVersionMigratorExpansion +} + +// kubeStorageVersionMigrators implements KubeStorageVersionMigratorInterface +type kubeStorageVersionMigrators struct { + client rest.Interface +} + +// newKubeStorageVersionMigrators returns a KubeStorageVersionMigrators +func newKubeStorageVersionMigrators(c *OperatorV1Client) *kubeStorageVersionMigrators { + return &kubeStorageVersionMigrators{ + client: c.RESTClient(), + } +} + +// Get takes name of the kubeStorageVersionMigrator, and returns the corresponding kubeStorageVersionMigrator object, and an error if there is any. +func (c *kubeStorageVersionMigrators) Get(name string, options metav1.GetOptions) (result *v1.KubeStorageVersionMigrator, err error) { + result = &v1.KubeStorageVersionMigrator{} + err = c.client.Get(). + Resource("kubestorageversionmigrators"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of KubeStorageVersionMigrators that match those selectors. +func (c *kubeStorageVersionMigrators) List(opts metav1.ListOptions) (result *v1.KubeStorageVersionMigratorList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.KubeStorageVersionMigratorList{} + err = c.client.Get(). + Resource("kubestorageversionmigrators"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested kubeStorageVersionMigrators. +func (c *kubeStorageVersionMigrators) Watch(opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("kubestorageversionmigrators"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch() +} + +// Create takes the representation of a kubeStorageVersionMigrator and creates it. Returns the server's representation of the kubeStorageVersionMigrator, and an error, if there is any. +func (c *kubeStorageVersionMigrators) Create(kubeStorageVersionMigrator *v1.KubeStorageVersionMigrator) (result *v1.KubeStorageVersionMigrator, err error) { + result = &v1.KubeStorageVersionMigrator{} + err = c.client.Post(). + Resource("kubestorageversionmigrators"). + Body(kubeStorageVersionMigrator). + Do(). + Into(result) + return +} + +// Update takes the representation of a kubeStorageVersionMigrator and updates it. Returns the server's representation of the kubeStorageVersionMigrator, and an error, if there is any. +func (c *kubeStorageVersionMigrators) Update(kubeStorageVersionMigrator *v1.KubeStorageVersionMigrator) (result *v1.KubeStorageVersionMigrator, err error) { + result = &v1.KubeStorageVersionMigrator{} + err = c.client.Put(). + Resource("kubestorageversionmigrators"). + Name(kubeStorageVersionMigrator.Name). + Body(kubeStorageVersionMigrator). + Do(). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + +func (c *kubeStorageVersionMigrators) UpdateStatus(kubeStorageVersionMigrator *v1.KubeStorageVersionMigrator) (result *v1.KubeStorageVersionMigrator, err error) { + result = &v1.KubeStorageVersionMigrator{} + err = c.client.Put(). + Resource("kubestorageversionmigrators"). + Name(kubeStorageVersionMigrator.Name). + SubResource("status"). + Body(kubeStorageVersionMigrator). + Do(). + Into(result) + return +} + +// Delete takes name of the kubeStorageVersionMigrator and deletes it. Returns an error if one occurs. +func (c *kubeStorageVersionMigrators) Delete(name string, options *metav1.DeleteOptions) error { + return c.client.Delete(). + Resource("kubestorageversionmigrators"). + Name(name). + Body(options). + Do(). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *kubeStorageVersionMigrators) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error { + var timeout time.Duration + if listOptions.TimeoutSeconds != nil { + timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("kubestorageversionmigrators"). + VersionedParams(&listOptions, scheme.ParameterCodec). + Timeout(timeout). + Body(options). + Do(). + Error() +} + +// Patch applies the patch and returns the patched kubeStorageVersionMigrator. +func (c *kubeStorageVersionMigrators) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.KubeStorageVersionMigrator, err error) { + result = &v1.KubeStorageVersionMigrator{} + err = c.client.Patch(pt). + Resource("kubestorageversionmigrators"). + SubResource(subresources...). + Name(name). + Body(data). + Do(). + Into(result) + return +} diff --git a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/operator_client.go b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/operator_client.go index 53f2cb3e95..b6e2f95b3b 100644 --- a/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/operator_client.go +++ b/vendor/github.com/openshift/client-go/operator/clientset/versioned/typed/operator/v1/operator_client.go @@ -18,6 +18,7 @@ type OperatorV1Interface interface { KubeAPIServersGetter KubeControllerManagersGetter KubeSchedulersGetter + KubeStorageVersionMigratorsGetter NetworksGetter OpenShiftAPIServersGetter OpenShiftControllerManagersGetter @@ -63,6 +64,10 @@ func (c *OperatorV1Client) KubeSchedulers() KubeSchedulerInterface { return newKubeSchedulers(c) } +func (c *OperatorV1Client) KubeStorageVersionMigrators() KubeStorageVersionMigratorInterface { + return newKubeStorageVersionMigrators(c) +} + func (c *OperatorV1Client) Networks() NetworkInterface { return newNetworks(c) } diff --git a/vendor/github.com/openshift/client-go/operator/informers/externalversions/generic.go b/vendor/github.com/openshift/client-go/operator/informers/externalversions/generic.go index 8795ae8a09..b5b19516f0 100644 --- a/vendor/github.com/openshift/client-go/operator/informers/externalversions/generic.go +++ b/vendor/github.com/openshift/client-go/operator/informers/externalversions/generic.go @@ -54,6 +54,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1().KubeControllerManagers().Informer()}, nil case v1.SchemeGroupVersion.WithResource("kubeschedulers"): return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1().KubeSchedulers().Informer()}, nil + case v1.SchemeGroupVersion.WithResource("kubestorageversionmigrators"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1().KubeStorageVersionMigrators().Informer()}, nil case v1.SchemeGroupVersion.WithResource("networks"): return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1().Networks().Informer()}, nil case v1.SchemeGroupVersion.WithResource("openshiftapiservers"): diff --git a/vendor/github.com/openshift/client-go/operator/informers/externalversions/operator/v1/interface.go b/vendor/github.com/openshift/client-go/operator/informers/externalversions/operator/v1/interface.go index 06963ddc24..5b6985a6d9 100644 --- a/vendor/github.com/openshift/client-go/operator/informers/externalversions/operator/v1/interface.go +++ b/vendor/github.com/openshift/client-go/operator/informers/externalversions/operator/v1/interface.go @@ -24,6 +24,8 @@ type Interface interface { KubeControllerManagers() KubeControllerManagerInformer // KubeSchedulers returns a KubeSchedulerInformer. KubeSchedulers() KubeSchedulerInformer + // KubeStorageVersionMigrators returns a KubeStorageVersionMigratorInformer. + KubeStorageVersionMigrators() KubeStorageVersionMigratorInformer // Networks returns a NetworkInformer. Networks() NetworkInformer // OpenShiftAPIServers returns a OpenShiftAPIServerInformer. @@ -89,6 +91,11 @@ func (v *version) KubeSchedulers() KubeSchedulerInformer { return &kubeSchedulerInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} } +// KubeStorageVersionMigrators returns a KubeStorageVersionMigratorInformer. +func (v *version) KubeStorageVersionMigrators() KubeStorageVersionMigratorInformer { + return &kubeStorageVersionMigratorInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + // Networks returns a NetworkInformer. func (v *version) Networks() NetworkInformer { return &networkInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} diff --git a/vendor/github.com/openshift/client-go/operator/informers/externalversions/operator/v1/kubestorageversionmigrator.go b/vendor/github.com/openshift/client-go/operator/informers/externalversions/operator/v1/kubestorageversionmigrator.go new file mode 100644 index 0000000000..fe35406df2 --- /dev/null +++ b/vendor/github.com/openshift/client-go/operator/informers/externalversions/operator/v1/kubestorageversionmigrator.go @@ -0,0 +1,72 @@ +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + time "time" + + operatorv1 "github.com/openshift/api/operator/v1" + versioned "github.com/openshift/client-go/operator/clientset/versioned" + internalinterfaces "github.com/openshift/client-go/operator/informers/externalversions/internalinterfaces" + v1 "github.com/openshift/client-go/operator/listers/operator/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// KubeStorageVersionMigratorInformer provides access to a shared informer and lister for +// KubeStorageVersionMigrators. +type KubeStorageVersionMigratorInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.KubeStorageVersionMigratorLister +} + +type kubeStorageVersionMigratorInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewKubeStorageVersionMigratorInformer constructs a new informer for KubeStorageVersionMigrator type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewKubeStorageVersionMigratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredKubeStorageVersionMigratorInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredKubeStorageVersionMigratorInformer constructs a new informer for KubeStorageVersionMigrator type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredKubeStorageVersionMigratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.OperatorV1().KubeStorageVersionMigrators().List(options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.OperatorV1().KubeStorageVersionMigrators().Watch(options) + }, + }, + &operatorv1.KubeStorageVersionMigrator{}, + resyncPeriod, + indexers, + ) +} + +func (f *kubeStorageVersionMigratorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredKubeStorageVersionMigratorInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *kubeStorageVersionMigratorInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&operatorv1.KubeStorageVersionMigrator{}, f.defaultInformer) +} + +func (f *kubeStorageVersionMigratorInformer) Lister() v1.KubeStorageVersionMigratorLister { + return v1.NewKubeStorageVersionMigratorLister(f.Informer().GetIndexer()) +} diff --git a/vendor/github.com/openshift/client-go/operator/listers/operator/v1/expansion_generated.go b/vendor/github.com/openshift/client-go/operator/listers/operator/v1/expansion_generated.go index 5db9c1f820..3322edf340 100644 --- a/vendor/github.com/openshift/client-go/operator/listers/operator/v1/expansion_generated.go +++ b/vendor/github.com/openshift/client-go/operator/listers/operator/v1/expansion_generated.go @@ -38,6 +38,10 @@ type KubeControllerManagerListerExpansion interface{} // KubeSchedulerLister. type KubeSchedulerListerExpansion interface{} +// KubeStorageVersionMigratorListerExpansion allows custom methods to be added to +// KubeStorageVersionMigratorLister. +type KubeStorageVersionMigratorListerExpansion interface{} + // NetworkListerExpansion allows custom methods to be added to // NetworkLister. type NetworkListerExpansion interface{} diff --git a/vendor/github.com/openshift/client-go/operator/listers/operator/v1/kubestorageversionmigrator.go b/vendor/github.com/openshift/client-go/operator/listers/operator/v1/kubestorageversionmigrator.go new file mode 100644 index 0000000000..dc2c1f98ca --- /dev/null +++ b/vendor/github.com/openshift/client-go/operator/listers/operator/v1/kubestorageversionmigrator.go @@ -0,0 +1,49 @@ +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/openshift/api/operator/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// KubeStorageVersionMigratorLister helps list KubeStorageVersionMigrators. +type KubeStorageVersionMigratorLister interface { + // List lists all KubeStorageVersionMigrators in the indexer. + List(selector labels.Selector) (ret []*v1.KubeStorageVersionMigrator, err error) + // Get retrieves the KubeStorageVersionMigrator from the index for a given name. + Get(name string) (*v1.KubeStorageVersionMigrator, error) + KubeStorageVersionMigratorListerExpansion +} + +// kubeStorageVersionMigratorLister implements the KubeStorageVersionMigratorLister interface. +type kubeStorageVersionMigratorLister struct { + indexer cache.Indexer +} + +// NewKubeStorageVersionMigratorLister returns a new KubeStorageVersionMigratorLister. +func NewKubeStorageVersionMigratorLister(indexer cache.Indexer) KubeStorageVersionMigratorLister { + return &kubeStorageVersionMigratorLister{indexer: indexer} +} + +// List lists all KubeStorageVersionMigrators in the indexer. +func (s *kubeStorageVersionMigratorLister) List(selector labels.Selector) (ret []*v1.KubeStorageVersionMigrator, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.KubeStorageVersionMigrator)) + }) + return ret, err +} + +// Get retrieves the KubeStorageVersionMigrator from the index for a given name. +func (s *kubeStorageVersionMigratorLister) Get(name string) (*v1.KubeStorageVersionMigrator, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("kubestorageversionmigrator"), name) + } + return obj.(*v1.KubeStorageVersionMigrator), nil +} diff --git a/vendor/github.com/openshift/library-go/Makefile b/vendor/github.com/openshift/library-go/Makefile index 2704d89e47..8f164242c6 100644 --- a/vendor/github.com/openshift/library-go/Makefile +++ b/vendor/github.com/openshift/library-go/Makefile @@ -18,3 +18,6 @@ $(call add-bindata,backingresources,./pkg/operator/staticpod/controller/backingr $(call add-bindata,monitoring,./pkg/operator/staticpod/controller/monitoring/manifests/...,bindata,bindata,./pkg/operator/staticpod/controller/monitoring/bindata/bindata.go) $(call add-bindata,installer,./pkg/operator/staticpod/controller/installer/manifests/...,bindata,bindata,./pkg/operator/staticpod/controller/installer/bindata/bindata.go) $(call add-bindata,staticpod,./pkg/operator/staticpod/controller/prune/manifests/...,bindata,bindata,./pkg/operator/staticpod/controller/prune/bindata/bindata.go) + +test-e2e-encryption: GO_TEST_PACKAGES :=./test/e2e-encryption/... +.PHONY: test-e2e-encryption \ No newline at end of file diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/Makefile b/vendor/github.com/openshift/library-go/alpha-build-machinery/Makefile index 2ec73b0875..b44d020e4b 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/Makefile +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/Makefile @@ -14,6 +14,7 @@ examples :=$(wildcard ./make/examples/*/Makefile.test) # Delete lines referencing temporary files and directories # Unify make error output between versions # Ignore old cp errors on centos7 +# Ignore different make output with `-k` option define update-makefile-log mkdir -p "$(3)" set -o pipefail; $(MAKE) -j 1 -C "$(dir $(1))" -f "$(notdir $(1))" --no-print-directory --warn-undefined-variables $(2) 2>&1 | \ @@ -24,6 +25,7 @@ set -o pipefail; $(MAKE) -j 1 -C "$(dir $(1))" -f "$(notdir $(1))" --no-print-di sed -E 's~^[<> ]*((\+\+\+|\-\-\-) \./(testing/)?manifests/.*.yaml).*~\1~' | \ sed -E 's/^(make\[2\]: \*\*\* \[).*: (.*\] Error 1)/\1\2/' | \ grep -v 'are the same file' | \ + grep -E -v -e '^make\[2\]: Target `.*'"'"' not remade because of errors\.$$' | \ tee "$(3)"/"$(notdir $(1))"$(subst ..,.,.$(2).log) endef diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.mk index 564fc12297..30806edb12 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/default.mk @@ -13,7 +13,7 @@ update: update-bindata # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ targets/openshift/deps.mk \ targets/openshift/images.mk \ diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile index 3ede7702ef..47380db0a5 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile @@ -2,11 +2,11 @@ include $(addprefix ../../, \ golang.mk \ targets/openshift/rpm.mk \ targets/openshift/crd-schema-gen.mk \ + targets/openshift/deps.mk \ ) # Set crd-schema-gen variables -CRD_SCHEMA_GEN_APIS :=$(addprefix ./pkg/apis/,v1 v1beta1) -CRD_SCHEMA_GEN_VERSION :=v0.2.1 +CRD_APIS :=$(addprefix ./pkg/apis/,v1 v1beta1) # rpm wants build-id set GO_LD_EXTRAFLAGS +=-B 0x$$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \n') @@ -15,6 +15,12 @@ OUTPUT_DIR :=_output CROSS_BUILD_BINDIR :=$(OUTPUT_DIR)/bin RPM_EXTRAFLAGS :=--quiet --define 'version 2.42.0' --define 'dist .el7' --define 'release 6' +# $1 - target name +# $2 - apis +# $3 - manifests +# $4 - output +$(call add-crd-gen,manifests,$(CRD_APIS),./manifests,./manifests) + cross-build-darwin-amd64: +@GOOS=darwin GOARCH=amd64 $(MAKE) --no-print-directory build GO_BUILD_BINDIR:=$(CROSS_BUILD_BINDIR)/darwin_amd64 .PHONY: cross-build-darwin-amd64 diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile.test.log b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile.test.log index c882560811..ef2631a76b 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile.test.log +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/Makefile.test.log @@ -17,10 +17,8 @@ make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' @@ -31,24 +29,18 @@ make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi [[ ! -d ./_output/ ]] || (ls -l ./_output/ && false) -make cross-build -fatal: No names found, cannot describe anything. -fatal: No names found, cannot describe anything. +make cross-build SOURCE_GIT_TAG=v42.43.44 SOURCE_GIT_COMMIT=aaa SOURCE_GIT_TREE_STATE=clean mkdir -p '_output/bin/darwin_amd64' go build -ldflags "-s -w -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.versionFromGit="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.commitFromGit="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.gitTreeState="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.buildDate="" -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \n')" -o '_output/bin/darwin_amd64/oc' github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/cmd/oc mkdir -p '_output/bin/darwin_amd64' go build -ldflags "-s -w -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.versionFromGit="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.commitFromGit="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.gitTreeState="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.buildDate="" -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \n')" -o '_output/bin/darwin_amd64/openshift' github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/cmd/openshift -fatal: No names found, cannot describe anything. -fatal: No names found, cannot describe anything. mkdir -p '_output/bin/windows_amd64' go build -ldflags "-s -w -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.versionFromGit="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.commitFromGit="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.gitTreeState="" -X github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/version.buildDate="" -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \n')" -o '_output/bin/windows_amd64/oc.exe' github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/cmd/oc mkdir -p '_output/bin/windows_amd64' @@ -63,10 +55,8 @@ make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' @@ -76,29 +66,23 @@ make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi [[ ! -d ./_output/ ]] || (ls -l ./_output/ && false) -make rpm-build +make rpm-build SOURCE_GIT_TAG=v42.43.44 SOURCE_GIT_COMMIT=aaa SOURCE_GIT_TREE_STATE=clean rpmbuild -ba --define "_topdir /github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries" --define "go_package github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries" --quiet --define 'version 2.42.0' --define 'dist .el7' --define 'release 6' ocp.spec -fatal: No names found, cannot describe anything. -fatal: No names found, cannot describe anything. [[ -f ./_output/rpms/x86_64/openshift-2.42.0-6.el7.x86_64.rpm ]] [[ -f ./_output/srpms/openshift-2.42.0-6.el7.src.rpm ]] make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' @@ -108,10 +92,8 @@ make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' @@ -119,47 +101,22 @@ if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi cp -r ./testing/manifests/initial/* ./manifests/ diff -Naup ./testing/manifests/initial/ ./manifests/ ! make verify-codegen-crds -Installing controller-gen into "_output/tools/src/sigs.k8s.io/controller-tools/controller-gen" -mkdir -p '_output/tools/src/sigs.k8s.io/controller-tools' -git clone -b 'v0.2.1' --single-branch --depth=1 https://github.com/kubernetes-sigs/controller-tools.git '_output/tools/src/sigs.k8s.io/controller-tools' -Cloning into '_output/tools/src/sigs.k8s.io/controller-tools'... -Note: checking out 'ba11932048e4538f6e435f5ca0cdea19bf458338'. - -You are in 'detached HEAD' state. You can look around, make experimental -changes and commit them, and you can discard any commits you make in this -state without impacting any branches by performing another checkout. - -If you want to create a new branch to retain commits you create, you may -do so (now or later) by using -b with the checkout command again. Example: - - -_output/tools/src/sigs.k8s.io/controller-tools/../.. -cd '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src' && go mod vendor 2>/dev/null && go build -mod=vendor ./cmd/controller-gen +Installing controller-gen into '_output/tools/bin/controller-gen' +mkdir -p '_output/tools/bin/' +curl -s -f -L https://github.com/openshift/kubernetes-sigs-controller-tools/releases/download/v0.2.1-37-ga3cca5d/controller-gen-linux-amd64 -o '_output/tools/bin/controller-gen' +chmod +x '_output/tools/bin/controller-gen'; Installing yq into '_output/tools/bin/yq' mkdir -p '_output/tools/bin/' curl -s -f -L https://github.com/mikefarah/yq/releases/download/2.4.0/yq_linux_amd64 -o '_output/tools/bin/yq' chmod +x '_output/tools/bin/yq'; -'_output/tools/src/sigs.k8s.io/controller-tools/controller-gen' \ - schemapatch:manifests="./manifests" \ - paths="./pkg/apis/v1;./pkg/apis/v1beta1" \ --- ./manifests/operator.openshift.io_myotheroperatorresources.crd.yaml -@@ -11,9 +11,39 @@ spec: +@@ -9,6 +9,40 @@ spec: + kind: MyOtherOperatorResource + plural: myotheroperatorresources scope: "" - version: v1beta1 - versions: -- - name: v1beta1 -- served: true -- storage: true -+ - name: v1beta1 -+ served: true -+ storage: true -+ "validation": -+ "openAPIV3Schema": ++ validation: ++ openAPIV3Schema: + description: MyOtherOperatorResource is an example operator configuration type -+ type: object -+ required: -+ - metadata -+ - spec + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation @@ -174,105 +131,45 @@ chmod +x '_output/tools/bin/yq'; + metadata: + type: object + spec: -+ type: object -+ required: -+ - deprecatedField -+ - name + properties: + deprecatedField: + type: string + name: + type: string - status: - acceptedNames: - kind: "" -make[2]: *** [verify-codegen-crds] Error 1 ++ overwritePattern: ++ pattern: ^(Managed|Unmanaged)$ ++ type: string ++ required: ++ - deprecatedField ++ - name ++ - overwritePattern ++ type: object ++ required: ++ - metadata ++ - spec ++ type: object + version: v1beta1 + versions: + - name: v1beta1 +make[2]: *** [verify-codegen-crds-manifests] Error 1 make update-codegen-crds -Using existing controller-gen from "_output/tools/src/sigs.k8s.io/controller-tools/controller-gen" +Using existing controller-gen from "_output/tools/bin/controller-gen" Using existing yq from "_output/tools/bin/yq" -'_output/tools/src/sigs.k8s.io/controller-tools/controller-gen' \ - schemapatch:manifests="./manifests" \ - paths="./pkg/apis/v1;./pkg/apis/v1beta1" \ - output:dir="./manifests" -cp -n ./manifests/operator.openshift.io_myoperatorresources.crd.yaml-merge-patch './manifests/' || true # FIXME: centos -_output/tools/bin/yq m -i './manifests/operator.openshift.io_myoperatorresources.crd.yaml' './manifests/operator.openshift.io_myoperatorresources.crd.yaml-merge-patch' +'_output/tools/bin/controller-gen' schemapatch:manifests="./manifests" paths="./pkg/apis/v1;./pkg/apis/v1beta1" output:dir="./manifests" +_output/tools/bin/yq m -i -x './manifests/operator.openshift.io_myotheroperatorresources.crd.yaml' './manifests/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch' +_output/tools/bin/yq m -i -x './manifests/operator.openshift.io_myoperatorresources.crd.yaml' './manifests/operator.openshift.io_myoperatorresources.crd.yaml-merge-patch' make verify-codegen-crds -Using existing controller-gen from "_output/tools/src/sigs.k8s.io/controller-tools/controller-gen" +Using existing controller-gen from "_output/tools/bin/controller-gen" Using existing yq from "_output/tools/bin/yq" -'_output/tools/src/sigs.k8s.io/controller-tools/controller-gen' \ - schemapatch:manifests="./manifests" \ - paths="./pkg/apis/v1;./pkg/apis/v1beta1" \ -! diff -Naup ./testing/manifests/initial/ ./manifests/ 2>/dev/null -diff -Naup ./testing/manifests/initial/operator.openshift.io_myoperatorresources.crd.yaml ./manifests/operator.openshift.io_myoperatorresources.crd.yaml ---- ./testing/manifests/initial/operator.openshift.io_myoperatorresources.crd.yaml -+++ ./manifests/operator.openshift.io_myoperatorresources.crd.yaml -@@ -9,6 +9,11 @@ spec: - kind: MyOperatorResource - plural: myoperatorresources - scope: "" -+ validation: -+ openAPIV3Schema: -+ properties: -+ apiVersion: -+ pattern: ^(test|TEST)$ - status: - acceptedNames: - kind: "" -diff -Naup ./testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml ./manifests/operator.openshift.io_myotheroperatorresources.crd.yaml ---- ./testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml -+++ ./manifests/operator.openshift.io_myotheroperatorresources.crd.yaml -@@ -11,9 +11,39 @@ spec: - scope: "" - version: v1beta1 - versions: -- - name: v1beta1 -- served: true -- storage: true -+ - name: v1beta1 -+ served: true -+ storage: true -+ "validation": -+ "openAPIV3Schema": -+ description: MyOtherOperatorResource is an example operator configuration type -+ type: object -+ required: -+ - metadata -+ - spec -+ 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: -+ type: object -+ required: -+ - deprecatedField -+ - name -+ properties: -+ deprecatedField: -+ type: string -+ name: -+ type: string - status: - acceptedNames: - kind: "" -diff -Naup ./testing/manifests/updated/ ./manifests/ 2>/dev/null +cp -r ./testing/manifests/initial/*.crd.yaml-merge-patch ./manifests/ +! diff -Naup ./testing/manifests/initial/ ./manifests/ 2>/dev/null 1>&2 +diff -Naup ./testing/manifests/updated/ ./manifests/ make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' @@ -282,10 +179,8 @@ make clean rm -f oc openshift rm -f -r '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/srpms' if [ -d '_output' ]; then rmdir --ignore-fail-on-non-empty '_output'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi -rm -f -r '_output/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod' -if [ -d '_output/tools/src/sigs.k8s.io/controller-tools' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/src/sigs.k8s.io/controller-tools'; fi -if [ -d '/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/_output/tools/src/pkg/mod'; fi +rm -f '_output/tools/bin/controller-gen' +if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f '_output/tools/bin/yq' if [ -d '_output/tools/bin/' ]; then rmdir --ignore-fail-on-non-empty -p '_output/tools/bin/'; fi rm -f -r '_output/bin' diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/glide.lock b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/glide.lock new file mode 100644 index 0000000000..339b04e1a0 --- /dev/null +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/glide.lock @@ -0,0 +1,61 @@ +hash: 1aaf998ca41bbf291600272fff83e55b5e9536f817ab15aedb2fa9459b15336f +updated: 2019-10-07T15:28:28.103413125+02:00 +imports: +- name: github.com/gogo/protobuf + version: 65acae22fc9d1fe290b33faa2bd64cdc20a463a0 + subpackages: + - proto + - sortkeys +- name: github.com/google/gofuzz + version: f140a6486e521aad38f5917de355cbf147cc0496 +- name: github.com/openshift/api + version: d92789481b059132f1febccd9bb47cb27220f248 + subpackages: + - config/v1 +- name: golang.org/x/net + version: cdfb69ac37fc6fa907650654115ebebb3aae2087 + subpackages: + - http/httpguts + - http2 + - http2/hpack + - idna +- name: golang.org/x/text + version: e6919f6577db79269a6443b9dc46d18f2238fb5d + subpackages: + - secure/bidirule + - transform + - unicode/bidi + - unicode/norm +- name: gopkg.in/inf.v0 + version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4 +- name: k8s.io/api + version: 95b840bb6a1f5f0462af804c8589396d294d4914 + subpackages: + - core/v1 +- name: k8s.io/apimachinery + version: 27d36303b6556f377b4f34e64705fa9024a12b0c + subpackages: + - pkg/api/resource + - pkg/apis/meta/v1 + - pkg/conversion + - pkg/conversion/queryparams + - pkg/fields + - pkg/labels + - pkg/runtime + - pkg/runtime/schema + - pkg/selection + - pkg/types + - pkg/util/errors + - pkg/util/intstr + - pkg/util/json + - pkg/util/naming + - pkg/util/net + - pkg/util/runtime + - pkg/util/sets + - pkg/util/validation + - pkg/util/validation/field + - pkg/watch + - third_party/forked/golang/reflect +- name: k8s.io/klog + version: 3ca30a56d8a775276f9cdae009ba326fdc05af7f +testImports: [] diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/glide.yaml b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/glide.yaml new file mode 100644 index 0000000000..1c5768bcdf --- /dev/null +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/glide.yaml @@ -0,0 +1,4 @@ +package: github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries +import: +- package: github.com/openshift/api +- package: k8s.io/apimachinery diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/manifests/operator.openshift.io_myotheroperatorresources.crd.yaml b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/manifests/operator.openshift.io_myotheroperatorresources.crd.yaml index 9ceac76344..05363164d3 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/manifests/operator.openshift.io_myotheroperatorresources.crd.yaml +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/manifests/operator.openshift.io_myotheroperatorresources.crd.yaml @@ -9,18 +9,9 @@ spec: kind: MyOtherOperatorResource plural: myotheroperatorresources scope: "" - version: v1beta1 - versions: - - name: v1beta1 - served: true - storage: true - "validation": - "openAPIV3Schema": + validation: + openAPIV3Schema: description: MyOtherOperatorResource is an example operator configuration type - type: object - required: - - metadata - - spec properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -35,15 +26,28 @@ spec: metadata: type: object spec: - type: object - required: - - deprecatedField - - name properties: deprecatedField: type: string name: type: string + overwritePattern: + pattern: ^(Managed|Unmanaged)$ + type: string + required: + - deprecatedField + - name + - overwritePattern + type: object + required: + - metadata + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true status: acceptedNames: kind: "" diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/manifests/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/manifests/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch new file mode 100644 index 0000000000..1eebf507ec --- /dev/null +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/manifests/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch @@ -0,0 +1,8 @@ +spec: + validation: + openAPIV3Schema: + properties: + spec: + properties: + overwritePattern: + pattern: ^(Managed|Unmanaged)$ diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/apis/v1beta1/types.go b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/apis/v1beta1/types.go index 5c1787309e..9169f90a61 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/apis/v1beta1/types.go +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/pkg/apis/v1beta1/types.go @@ -22,4 +22,7 @@ type MyOtherOperatorResource struct { type MyOtherOperatorResourceSpec struct { Name string `json:"name"` DeprecatedField string `json:"deprecatedField"` + + // +kubebuilder:validation:Pattern=^(Managed|Unmanaged)$ + OverwritePattern string `json:"overwritePattern"` } diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml index 622a5279af..fe529245e9 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml @@ -11,9 +11,9 @@ spec: scope: "" version: v1beta1 versions: - - name: v1beta1 - served: true - storage: true + - name: v1beta1 + served: true + storage: true status: acceptedNames: kind: "" diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch new file mode 100644 index 0000000000..1eebf507ec --- /dev/null +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/initial/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch @@ -0,0 +1,8 @@ +spec: + validation: + openAPIV3Schema: + properties: + spec: + properties: + overwritePattern: + pattern: ^(Managed|Unmanaged)$ diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/updated/operator.openshift.io_myotheroperatorresources.crd.yaml b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/updated/operator.openshift.io_myotheroperatorresources.crd.yaml index 9ceac76344..05363164d3 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/updated/operator.openshift.io_myotheroperatorresources.crd.yaml +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/updated/operator.openshift.io_myotheroperatorresources.crd.yaml @@ -9,18 +9,9 @@ spec: kind: MyOtherOperatorResource plural: myotheroperatorresources scope: "" - version: v1beta1 - versions: - - name: v1beta1 - served: true - storage: true - "validation": - "openAPIV3Schema": + validation: + openAPIV3Schema: description: MyOtherOperatorResource is an example operator configuration type - type: object - required: - - metadata - - spec properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -35,15 +26,28 @@ spec: metadata: type: object spec: - type: object - required: - - deprecatedField - - name properties: deprecatedField: type: string name: type: string + overwritePattern: + pattern: ^(Managed|Unmanaged)$ + type: string + required: + - deprecatedField + - name + - overwritePattern + type: object + required: + - metadata + - spec + type: object + version: v1beta1 + versions: + - name: v1beta1 + served: true + storage: true status: acceptedNames: kind: "" diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/updated/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/updated/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch new file mode 100644 index 0000000000..1eebf507ec --- /dev/null +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/examples/multiple-binaries/testing/manifests/updated/operator.openshift.io_myotheroperatorresources.crd.yaml-merge-patch @@ -0,0 +1,8 @@ +spec: + validation: + openAPIV3Schema: + properties: + spec: + properties: + overwritePattern: + pattern: ^(Managed|Unmanaged)$ diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/lib/golang.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/lib/golang.mk index 2184f17483..89d457ef0e 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/lib/golang.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/lib/golang.mk @@ -12,7 +12,7 @@ GOFMT ?=gofmt GOFMT_FLAGS ?=-s -l GOLINT ?=golint -GO_FILES ?=$(shell find . -name '*.go' -not -path './vendor/*' -print) +GO_FILES ?=$(shell find . -name '*.go' -not -path '*/vendor/*' -not -path '*/_output/*' -print) GO_PACKAGES ?=./... GO_TEST_PACKAGES ?=$(GO_PACKAGES) diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/build.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/build.mk index 9a71cb793a..07c15faa42 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/build.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/build.mk @@ -22,7 +22,7 @@ clean: clean-binaries # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ ../../lib/golang.mk \ ) diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/test-unit.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/test-unit.mk index f96c8ccd73..908783aac0 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/test-unit.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/test-unit.mk @@ -13,7 +13,7 @@ endif # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ ../../lib/golang.mk \ ) diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/verify-update.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/verify-update.mk index 2034cd10e1..78b2783baf 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/verify-update.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/golang/verify-update.mk @@ -28,7 +28,7 @@ verify-golint: # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ ../../lib/golang.mk \ ) diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/bindata.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/bindata.mk index 0e78cb9274..97b7bd36d3 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/bindata.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/bindata.mk @@ -3,7 +3,7 @@ TMP_GOPATH :=$(shell mktemp -d) .ensure-go-bindata: ln -s $(abspath ./vendor) "$(TMP_GOPATH)/src" - export GOPATH=$(TMP_GOPATH) && export GOBIN=$(TMP_GOPATH)/bin && go install "./vendor/github.com/jteeuwen/go-bindata/..." + export GO111MODULE=off && export GOPATH=$(TMP_GOPATH) && export GOBIN=$(TMP_GOPATH)/bin && go install "./vendor/github.com/jteeuwen/go-bindata/..." # $1 - input dirs # $2 - prefix diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/controller-gen.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/controller-gen.mk index fd0ff401e8..eeb29d7d35 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/controller-gen.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/controller-gen.mk @@ -1,37 +1,30 @@ self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) -CONTROLLER_GEN_VERSION ?=v0.2.1 -CONTROLLER_GEN_TEMP ?=$(PERMANENT_TMP_GOPATH)/src/sigs.k8s.io/controller-tools -controller_gen_gopath =$(shell realpath -m $(CONTROLLER_GEN_TEMP)/../..) -CONTROLLER_GEN ?=$(CONTROLLER_GEN_TEMP)/controller-gen +CONTROLLER_GEN_VERSION ?=v0.2.1-37-ga3cca5d +CONTROLLER_GEN ?=$(PERMANENT_TMP_GOPATH)/bin/controller-gen +controller_gen_dir :=$(dir $(CONTROLLER_GEN)) ensure-controller-gen: ifeq "" "$(wildcard $(CONTROLLER_GEN))" - $(info Installing controller-gen into "$(CONTROLLER_GEN)") - mkdir -p '$(CONTROLLER_GEN_TEMP)' - git clone -b '$(CONTROLLER_GEN_VERSION)' --single-branch --depth=1 https://github.com/kubernetes-sigs/controller-tools.git '$(CONTROLLER_GEN_TEMP)' - @echo '$(CONTROLLER_GEN_TEMP)/../..' - cd '$(CONTROLLER_GEN_TEMP)' && export GO111MODULE=on GOPATH='$(controller_gen_gopath)' && $(GO) mod vendor 2>/dev/null && $(GO) build -mod=vendor ./cmd/controller-gen + $(info Installing controller-gen into '$(CONTROLLER_GEN)') + mkdir -p '$(controller_gen_dir)' + curl -s -f -L https://github.com/openshift/kubernetes-sigs-controller-tools/releases/download/$(CONTROLLER_GEN_VERSION)/controller-gen-$(GOHOSTOS)-$(GOHOSTARCH) -o '$(CONTROLLER_GEN)' + chmod +x '$(CONTROLLER_GEN)'; else $(info Using existing controller-gen from "$(CONTROLLER_GEN)") endif .PHONY: ensure-controller-gen clean-controller-gen: - if [ -d '$(controller_gen_gopath)/pkg/mod' ]; then chmod +w -R '$(controller_gen_gopath)/pkg/mod'; fi - $(RM) -r '$(CONTROLLER_GEN_TEMP)' '$(controller_gen_gopath)/pkg/mod' - @mkdir -p '$(CONTROLLER_GEN_TEMP)' # to make sure we can do the next step and to avoid using '/*' wildcard on the line above which could go crazy on wrong substitution - if [ -d '$(CONTROLLER_GEN_TEMP)' ]; then rmdir --ignore-fail-on-non-empty -p '$(CONTROLLER_GEN_TEMP)'; fi - @mkdir -p '$(controller_gen_gopath)/pkg/mod' # to make sure we can do the next step and to avoid using '/*' wildcard on the line above which could go crazy on wrong substitution - if [ -d '$(controller_gen_gopath)/pkg/mod' ]; then rmdir --ignore-fail-on-non-empty -p '$(controller_gen_gopath)/pkg/mod'; fi + $(RM) '$(CONTROLLER_GEN)' + if [ -d '$(controller_gen_dir)' ]; then rmdir --ignore-fail-on-non-empty -p '$(controller_gen_dir)'; fi .PHONY: clean-controller-gen clean: clean-controller-gen - # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ ../../lib/golang.mk \ ../../lib/tmp.mk \ diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/crd-schema-gen.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/crd-schema-gen.mk index ac8038b839..2e152fd65e 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/crd-schema-gen.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/crd-schema-gen.mk @@ -1,46 +1,62 @@ self_dir :=$(dir $(lastword $(MAKEFILE_LIST))) -CRD_SCHEMA_GEN_APIS ?=$(error CRD_SCHEMA_GEN_APIS is required) -CRD_SCHEMA_GEN_MANIFESTS ?=./manifests -CRD_SCHEMA_GEN_OUTPUT ?=./manifests - -crd_patches =$(subst $(CRD_SCHEMA_GEN_MANIFESTS),$(CRD_SCHEMA_GEN_OUTPUT),$(wildcard $(CRD_SCHEMA_GEN_MANIFESTS)/*.crd.yaml-merge-patch)) - # $1 - crd file # $2 - patch file define patch-crd - cp -n $(CRD_SCHEMA_GEN_MANIFESTS)/$(notdir $2) '$(CRD_SCHEMA_GEN_OUTPUT)/' || true # FIXME: centos - $(YQ) m -i '$(1)' '$(2)' + $(YQ) m -i -x '$(1)' '$(2)' endef empty := -update-codegen-crds: ensure-controller-gen ensure-yq + +define diff-file + diff -Naup '$(1)' '$(2)' + +endef + +# $1 - apis +# $2 - manifests +# $3 - output +define run-crd-gen '$(CONTROLLER_GEN)' \ - schemapatch:manifests="$(CRD_SCHEMA_GEN_MANIFESTS)" \ - paths="$(subst $(empty) ,;,$(CRD_SCHEMA_GEN_APIS))" \ - output:dir="$(CRD_SCHEMA_GEN_OUTPUT)" - $(foreach p,$(crd_patches),$(call patch-crd,$(basename $(p)).yaml,$(p))) + schemapatch:manifests="$(2)" \ + paths="$(subst $(empty) ,;,$(1))" \ + output:dir="$(3)" + $$(foreach p,$$(wildcard $(2)/*.crd.yaml-merge-patch),$$(call patch-crd,$$(subst $(2),$(3),$$(basename $$(p))).yaml,$$(p))) +endef + + +# $1 - target name +# $2 - apis +# $3 - manifests +# $4 - output +define add-crd-gen-internal + +update-codegen-crds-$(1): ensure-controller-gen ensure-yq + $(call run-crd-gen,$(2),$(3),$(4)) +.PHONY: update-codegen-crds-$(1) + +update-codegen-crds: update-codegen-crds-$(1) .PHONY: update-codegen-crds +verify-codegen-crds-$(1): VERIFY_CODEGEN_CRD_TMP_DIR:=$(shell mktemp -d) +verify-codegen-crds-$(1): ensure-controller-gen ensure-yq + $(call run-crd-gen,$(2),$(3),$$(VERIFY_CODEGEN_CRD_TMP_DIR)) + $$(foreach p,$$(wildcard $(3)/*.crd.yaml),$$(call diff-file,$$(p),$$(subst $(3),$$(VERIFY_CODEGEN_CRD_TMP_DIR),$$(p)))) +.PHONY: verify-codegen-crds-$(1) + +verify-codegen-crds: verify-codegen-crds-$(1) +.PHONY: verify-codegen-crds + +endef + + update-generated: update-codegen-crds .PHONY: update-generated update: update-generated .PHONY: update -# $1 - manifest (actual) crd -# $2 - temp crd -define diff-crd - diff -Naup $(1) $(2) - -endef - -verify-codegen-crds: CRD_SCHEMA_GEN_OUTPUT :=$(shell mktemp -d) -verify-codegen-crds: update-codegen-crds - $(foreach p,$(wildcard $(CRD_SCHEMA_GEN_MANIFESTS)/*.crd.yaml),$(call diff-crd,$(p),$(subst $(CRD_SCHEMA_GEN_MANIFESTS),$(CRD_SCHEMA_GEN_OUTPUT),$(p)))) -.PHONY: verify-codegen-crds - verify-generated: verify-codegen-crds .PHONY: verify-generated @@ -48,9 +64,14 @@ verify: verify-generated .PHONY: verify +define add-crd-gen +$(eval $(call add-crd-gen-internal,$(1),$(2),$(3),$(4))) +endef + + # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ ../../lib/golang.mk \ ../../lib/tmp.mk \ diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/rpm.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/rpm.mk index b235197c74..3f20bb1ca9 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/rpm.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/rpm.mk @@ -35,7 +35,7 @@ clean: clean-rpms # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ ../../lib/golang.mk \ ) diff --git a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/yq.mk b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/yq.mk index 7dd556d400..2679e3add3 100644 --- a/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/yq.mk +++ b/vendor/github.com/openshift/library-go/alpha-build-machinery/make/targets/openshift/yq.mk @@ -25,7 +25,7 @@ clean: clean-yq # We need to be careful to expand all the paths before any include is done # or self_dir could be modified for the next include by the included file. -# Also doing this at the end of the file allows us to user self_dir before it could be modified. +# Also doing this at the end of the file allows us to use self_dir before it could be modified. include $(addprefix $(self_dir), \ ../../lib/golang.mk \ ../../lib/tmp.mk \ diff --git a/vendor/github.com/openshift/library-go/glide.lock b/vendor/github.com/openshift/library-go/glide.lock index edf88ee5d1..932525b29d 100644 --- a/vendor/github.com/openshift/library-go/glide.lock +++ b/vendor/github.com/openshift/library-go/glide.lock @@ -1,5 +1,5 @@ hash: a0b165129788498ed7cce6fbb74b199d93267da70ca145ed6f5fe489ccade8e6 -updated: 2019-09-27T10:23:18.38794-04:00 +updated: 2019-10-21T10:43:26.014139+02:00 imports: - name: bitbucket.org/ww/goautoneg version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 @@ -127,7 +127,7 @@ imports: - name: github.com/getsentry/raven-go version: c977f96e109525a5d8fa10a19165341f601f38b0 - name: github.com/ghodss/yaml - version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee + version: 25d852aebe32c875e9c044af3eef9c7dc6bc777f - name: github.com/go-openapi/jsonpointer version: 46af16f9f7b149af66e5d1bd010e3574dc06de98 - name: github.com/go-openapi/jsonreference @@ -210,7 +210,7 @@ imports: - compiler - extensions - name: github.com/gorilla/mux - version: 884b5ffcbd3a11b730f0b75f5c86ac408753c34d + version: ff4e71f144166b1dfe3017a146f8ed32a82e688b - name: github.com/grpc-ecosystem/go-grpc-prometheus version: c225b8c3b01faf2899099b768856a9e916e5087b - name: github.com/hashicorp/golang-lru @@ -259,12 +259,12 @@ imports: - specs-go - specs-go/v1 - name: github.com/opencontainers/runc - version: 84373aaa560b3f14cfda210b2f34ca14fd4b1fce + version: 4e3701702e966b4258fbab5b92efa6418c5ae6c6 subpackages: - libcontainer/system - libcontainer/user - name: github.com/openshift/api - version: 86c3b775619d6cd1f651ff52202431d0ffd69586 + version: d0b31d707c464221d1eb24846b0d0bbe57040102 subpackages: - apps - apps/v1 @@ -308,10 +308,8 @@ imports: - unidling/v1alpha1 - user - user/v1 - - webconsole - - webconsole/v1 - name: github.com/openshift/client-go - version: 3b6373338c9bb11fbcf329c25e81ae7e9a1ed8c6 + version: 3b0e988f8cb09a07f375dfc304b86c1a81cbc82b subpackages: - apps/clientset/versioned/scheme - apps/clientset/versioned/typed/apps/v1 @@ -320,6 +318,8 @@ imports: - config/clientset/versioned/scheme - config/clientset/versioned/typed/config/v1 - config/clientset/versioned/typed/config/v1/fake + - config/informers/externalversions + - config/informers/externalversions/config - config/informers/externalversions/config/v1 - config/informers/externalversions/internalinterfaces - config/listers/config/v1 @@ -344,6 +344,10 @@ imports: version: 645ef00459ed84a119197bfb8d8205042c6df63d - name: github.com/pkg/profile version: f6fe06335df110bcf1ed6d4e852b760bfc15beee +- name: github.com/pmezard/go-difflib + version: 792786c7400a136282c1664665ae0a8db921c6c2 + subpackages: + - difflib - name: github.com/prometheus/client_golang version: 505eaef017263e299324067d40ca2c48f6a2cf50 subpackages: @@ -378,6 +382,11 @@ imports: version: 67fc4837d267bc9bfd6e47f77783fcc3dffc68de - name: github.com/spf13/pflag version: 298182f68c66c05229eb03ac171abe6e309ee79a +- name: github.com/stretchr/testify + version: ffdc059bfe9ce6a4e144ba849dbedead332c6053 + subpackages: + - assert + - require - name: go.uber.org/atomic version: 8dc6146f7569370a472715e178d8ae31172ee6da - name: go.uber.org/multierr diff --git a/vendor/github.com/openshift/library-go/pkg/assets/create/creater.go b/vendor/github.com/openshift/library-go/pkg/assets/create/creater.go index cd5f6a7494..bf2bdf1a8d 100644 --- a/vendor/github.com/openshift/library-go/pkg/assets/create/creater.go +++ b/vendor/github.com/openshift/library-go/pkg/assets/create/creater.go @@ -263,7 +263,7 @@ func load(assetsDir string, options CreateOptions) (map[string]*unstructured.Uns } manifestUnstructured, ok := manifestObj.(*unstructured.Unstructured) if !ok { - errs[manifestPath] = fmt.Errorf("unable to convert asset %q to unstructed", manifestPath) + errs[manifestPath] = fmt.Errorf("unable to convert asset %q to unstructured", manifestPath) continue } manifests[manifestPath] = manifestUnstructured diff --git a/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go index 5a593d2b12..f82f550784 100644 --- a/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go +++ b/vendor/github.com/openshift/library-go/pkg/crypto/crypto.go @@ -31,7 +31,8 @@ import ( "k8s.io/client-go/util/cert" ) -// TLS versions that are known to golang. Go 1.12 adds TLS 1.3 support with a build flag. +// TLS versions that are known to golang. Go 1.13 adds support for +// TLS 1.3 that's opt-out with a build flag. var versions = map[string]uint16{ "VersionTLS10": tls.VersionTLS10, "VersionTLS11": tls.VersionTLS11, @@ -44,6 +45,7 @@ var supportedVersions = map[string]uint16{ "VersionTLS10": tls.VersionTLS10, "VersionTLS11": tls.VersionTLS11, "VersionTLS12": tls.VersionTLS12, + "VersionTLS13": tls.VersionTLS13, } // TLSVersionToNameOrDie given a tls version as an int, return its readable name @@ -107,6 +109,15 @@ func DefaultTLSVersion() uint16 { return tls.VersionTLS12 } +// ciphersTLS13 copies golang 1.13 implementation, where TLS1.3 suites are not +// configurable (cipherSuites field is ignored for TLS1.3 flows and all of the +// below three - and none other - are used) +var ciphersTLS13 = map[string]uint16{ + "TLS_AES_128_GCM_SHA256": tls.TLS_AES_128_GCM_SHA256, + "TLS_AES_256_GCM_SHA384": tls.TLS_AES_256_GCM_SHA384, + "TLS_CHACHA20_POLY1305_SHA256": tls.TLS_CHACHA20_POLY1305_SHA256, +} + var ciphers = map[string]uint16{ "TLS_RSA_WITH_RC4_128_SHA": tls.TLS_RSA_WITH_RC4_128_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA": tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, @@ -164,6 +175,11 @@ func CipherSuite(cipherName string) (uint16, error) { if cipher, ok := ciphers[cipherName]; ok { return cipher, nil } + + if _, ok := ciphersTLS13[cipherName]; ok { + return 0, fmt.Errorf("all golang TLSv1.3 ciphers are always used for TLSv1.3 flows") + } + return 0, fmt.Errorf("unknown cipher name %q", cipherName) } @@ -542,27 +558,36 @@ func MakeSelfSignedCA(certFile, keyFile, serialFile, name string, expireDays int } func MakeSelfSignedCAConfig(name string, expireDays int) (*TLSCertificateConfig, error) { + subject := pkix.Name{CommonName: name} + return MakeSelfSignedCAConfigForSubject(subject, expireDays) +} + +func MakeSelfSignedCAConfigForSubject(subject pkix.Name, expireDays int) (*TLSCertificateConfig, error) { var caLifetimeInDays = DefaultCACertificateLifetimeInDays if expireDays > 0 { caLifetimeInDays = expireDays } if caLifetimeInDays > DefaultCACertificateLifetimeInDays { - warnAboutCertificateLifeTime(name, DefaultCACertificateLifetimeInDays) + warnAboutCertificateLifeTime(subject.CommonName, DefaultCACertificateLifetimeInDays) } caLifetime := time.Duration(caLifetimeInDays) * 24 * time.Hour - - return MakeSelfSignedCAConfigForDuration(name, caLifetime) + return makeSelfSignedCAConfigForSubjectAndDuration(subject, caLifetime) } func MakeSelfSignedCAConfigForDuration(name string, caLifetime time.Duration) (*TLSCertificateConfig, error) { + subject := pkix.Name{CommonName: name} + return makeSelfSignedCAConfigForSubjectAndDuration(subject, caLifetime) +} + +func makeSelfSignedCAConfigForSubjectAndDuration(subject pkix.Name, caLifetime time.Duration) (*TLSCertificateConfig, error) { // Create CA cert rootcaPublicKey, rootcaPrivateKey, err := NewKeyPair() if err != nil { return nil, err } - rootcaTemplate := newSigningCertificateTemplateForDuration(pkix.Name{CommonName: name}, caLifetime, time.Now) + rootcaTemplate := newSigningCertificateTemplateForDuration(subject, caLifetime, time.Now) rootcaCert, err := signCertificate(rootcaTemplate, rootcaPublicKey, rootcaTemplate, rootcaPrivateKey) if err != nil { return nil, err diff --git a/vendor/github.com/openshift/library-go/pkg/crypto/crypto_test.go b/vendor/github.com/openshift/library-go/pkg/crypto/crypto_test.go index 8ccd02d58c..d6454cefd4 100644 --- a/vendor/github.com/openshift/library-go/pkg/crypto/crypto_test.go +++ b/vendor/github.com/openshift/library-go/pkg/crypto/crypto_test.go @@ -21,6 +21,7 @@ func TestConstantMaps(t *testing.T) { } discoveredVersions := map[string]bool{} discoveredCiphers := map[string]bool{} + discoveredCiphersTLS13 := map[string]bool{} for _, declName := range pkg.Scope().Names() { if strings.HasPrefix(declName, "VersionTLS") { discoveredVersions[declName] = true @@ -28,6 +29,9 @@ func TestConstantMaps(t *testing.T) { if strings.HasPrefix(declName, "TLS_RSA_") || strings.HasPrefix(declName, "TLS_ECDHE_") { discoveredCiphers[declName] = true } + if strings.HasPrefix(declName, "TLS_AES_") || strings.HasPrefix(declName, "TLS_CHACHA20_") { + discoveredCiphersTLS13[declName] = true + } } for k := range discoveredCiphers { @@ -41,6 +45,17 @@ func TestConstantMaps(t *testing.T) { } } + for k := range discoveredCiphersTLS13 { + if _, ok := ciphersTLS13[k]; !ok { + t.Errorf("discovered cipher tls.%s not in ciphers map", k) + } + } + for k := range ciphersTLS13 { + if _, ok := discoveredCiphersTLS13[k]; !ok { + t.Errorf("ciphersTLS13 map has %s not in tls package", k) + } + } + for k := range discoveredVersions { if _, ok := versions[k]; !ok { t.Errorf("discovered version tls.%s not in version map", k) diff --git a/vendor/github.com/openshift/library-go/pkg/image/registryclient/client.go b/vendor/github.com/openshift/library-go/pkg/image/registryclient/client.go index 0596a0dcf1..0429045655 100644 --- a/vendor/github.com/openshift/library-go/pkg/image/registryclient/client.go +++ b/vendor/github.com/openshift/library-go/pkg/image/registryclient/client.go @@ -20,6 +20,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/manifest/schema1" "github.com/docker/distribution/reference" + "github.com/docker/distribution/registry/api/errcode" registryclient "github.com/docker/distribution/registry/client" "github.com/docker/distribution/registry/client/auth" "github.com/docker/distribution/registry/client/auth/challenge" @@ -369,8 +370,20 @@ func isTemporaryHTTPError(err error) (time.Duration, bool) { switch t := err.(type) { case net.Error: return time.Second, t.Temporary() || t.Timeout() + case errcode.ErrorCoder: + // note: we explicitly do not check errcode.ErrorCodeUnknown because that is used in + // a wide range of scenarios to convey "generic error", not "retryable error" + switch t.ErrorCode() { + case errcode.ErrorCodeUnavailable: + return 5 * time.Second, true + case errcode.ErrorCodeTooManyRequests: + return 2 * time.Second, true + } case *registryclient.UnexpectedHTTPResponseError: - if t.StatusCode == http.StatusTooManyRequests { + switch t.StatusCode { + case http.StatusInternalServerError, http.StatusGatewayTimeout, http.StatusServiceUnavailable, http.StatusBadGateway: + return 5 * time.Second, true + case http.StatusTooManyRequests: return 2 * time.Second, true } } diff --git a/vendor/github.com/openshift/library-go/pkg/image/registryclient/client_test.go b/vendor/github.com/openshift/library-go/pkg/image/registryclient/client_test.go index 9fb65fb7a0..db1791a027 100644 --- a/vendor/github.com/openshift/library-go/pkg/image/registryclient/client_test.go +++ b/vendor/github.com/openshift/library-go/pkg/image/registryclient/client_test.go @@ -18,6 +18,7 @@ import ( "github.com/docker/distribution" "github.com/docker/distribution/reference" "github.com/docker/distribution/registry/api/errcode" + registryclient "github.com/docker/distribution/registry/client" "github.com/opencontainers/go-digest" "golang.org/x/net/context" ) @@ -320,13 +321,14 @@ func TestRetryFailure(t *testing.T) { t.Fatalf("unexpected: %v %v %#v", m, err, r) } - // retry four times + // verify docker known errors repo = &mockRepository{ getErr: temporaryError{}, blobs: &mockBlobStore{ - serveErr: temporaryError{}, - statErr: temporaryError{}, - openErr: temporaryError{}, + serveErr: errcode.ErrorCodeTooManyRequests.WithDetail(struct{}{}), + statErr: errcode.ErrorCodeUnavailable.WithDetail(struct{}{}), + // not retriable + openErr: errcode.ErrorCodeUnknown.WithDetail(struct{}{}), }, } r = NewLimitedRetryRepository(repo, 4, unlimited).(*retryRepository) @@ -335,7 +337,7 @@ func TestRetryFailure(t *testing.T) { if m, err = r.Manifests(ctx); err != nil { t.Fatal(err) } - r.retries = 2 + r.retries = 1 if _, err := m.Get(ctx, digest.Digest("foo")); err != repo.getErr { t.Fatalf("unexpected: %v %#v", err, r) } @@ -343,11 +345,12 @@ func TestRetryFailure(t *testing.T) { if m, err := m.Exists(ctx, "foo"); m || err != repo.getErr { t.Fatalf("unexpected: %v %v %#v", m, err, r) } - if sleeps != 4 { + if sleeps != 3 { t.Fatal(sleeps) } - r.retries = 2 + sleeps = 0 + r.retries = 1 b := r.Blobs(ctx) if err != nil { t.Fatal(err) @@ -359,10 +362,139 @@ func TestRetryFailure(t *testing.T) { if err := b.ServeBlob(ctx, nil, nil, digest.Digest("foo")); err != repo.blobs.serveErr { t.Fatalf("unexpected: %v %#v", err, r) } + r.retries = 4 + if _, err := b.Open(ctx, digest.Digest("foo")); err != repo.blobs.openErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + // Open did not retry + if sleeps != 3 { + t.Fatal(sleeps) + } + + // verify unknown client errors + repo = &mockRepository{ + getErr: temporaryError{}, + blobs: &mockBlobStore{ + serveErr: ®istryclient.UnexpectedHTTPResponseError{StatusCode: http.StatusTooManyRequests}, + statErr: ®istryclient.UnexpectedHTTPResponseError{StatusCode: http.StatusServiceUnavailable}, + openErr: ®istryclient.UnexpectedHTTPResponseError{StatusCode: http.StatusInternalServerError}, + }, + } + r = NewLimitedRetryRepository(repo, 4, unlimited).(*retryRepository) + sleeps = 0 + r.sleepFn = sleepFn + if m, err = r.Manifests(ctx); err != nil { + t.Fatal(err) + } + r.retries = 1 + if _, err := m.Get(ctx, digest.Digest("foo")); err != repo.getErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + r.retries = 2 + if m, err := m.Exists(ctx, "foo"); m || err != repo.getErr { + t.Fatalf("unexpected: %v %v %#v", m, err, r) + } + if sleeps != 3 { + t.Fatal(sleeps) + } + + sleeps = 0 + r.retries = 1 + b = r.Blobs(ctx) + if err != nil { + t.Fatal(err) + } + if _, err := b.Stat(ctx, digest.Digest("x")); err != repo.blobs.statErr { + t.Fatalf("unexpected: %v %#v", err, r) + } r.retries = 2 + if err := b.ServeBlob(ctx, nil, nil, digest.Digest("foo")); err != repo.blobs.serveErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + r.retries = 4 if _, err := b.Open(ctx, digest.Digest("foo")); err != repo.blobs.openErr { t.Fatalf("unexpected: %v %#v", err, r) } + // Open did not retry + if sleeps != 7 { + t.Fatal(sleeps) + } + + // verify more unknown client errors + repo = &mockRepository{ + getErr: temporaryError{}, + blobs: &mockBlobStore{ + serveErr: ®istryclient.UnexpectedHTTPResponseError{StatusCode: http.StatusBadGateway}, + statErr: ®istryclient.UnexpectedHTTPResponseError{StatusCode: http.StatusGatewayTimeout}, + openErr: ®istryclient.UnexpectedHTTPResponseError{StatusCode: http.StatusInternalServerError}, + }, + } + r = NewLimitedRetryRepository(repo, 4, unlimited).(*retryRepository) + sleeps = 0 + r.sleepFn = sleepFn + if m, err = r.Manifests(ctx); err != nil { + t.Fatal(err) + } + r.retries = 1 + if _, err := m.Get(ctx, digest.Digest("foo")); err != repo.getErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + r.retries = 2 + if m, err := m.Exists(ctx, "foo"); m || err != repo.getErr { + t.Fatalf("unexpected: %v %v %#v", m, err, r) + } + if sleeps != 3 { + t.Fatal(sleeps) + } + + sleeps = 0 + r.retries = 1 + b = r.Blobs(ctx) + if err != nil { + t.Fatal(err) + } + if _, err := b.Stat(ctx, digest.Digest("x")); err != repo.blobs.statErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + r.retries = 2 + if err := b.ServeBlob(ctx, nil, nil, digest.Digest("foo")); err != repo.blobs.serveErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + r.retries = 4 + if _, err := b.Open(ctx, digest.Digest("foo")); err != repo.blobs.openErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + // Open did not retry + if sleeps != 7 { + t.Fatal(sleeps) + } + + // retry with temporary errors + repo = &mockRepository{ + getErr: temporaryError{}, + blobs: &mockBlobStore{ + serveErr: temporaryError{}, + statErr: temporaryError{}, + openErr: temporaryError{}, + }, + } + r = NewLimitedRetryRepository(repo, 4, unlimited).(*retryRepository) + sleeps = 0 + r.sleepFn = sleepFn + if m, err = r.Manifests(ctx); err != nil { + t.Fatal(err) + } + r.retries = 1 + if _, err := m.Get(ctx, digest.Digest("foo")); err != repo.getErr { + t.Fatalf("unexpected: %v %#v", err, r) + } + r.retries = 2 + if m, err := m.Exists(ctx, "foo"); m || err != repo.getErr { + t.Fatalf("unexpected: %v %v %#v", m, err, r) + } + if sleeps != 3 { + t.Fatal(sleeps) + } } func Test_verifyManifest_Get(t *testing.T) { diff --git a/vendor/github.com/openshift/library-go/pkg/operator/configobserver/featuregates/observe_featuregates_test.go b/vendor/github.com/openshift/library-go/pkg/operator/configobserver/featuregates/observe_featuregates_test.go index 53aeb1a22e..aebdbd3abd 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/configobserver/featuregates/observe_featuregates_test.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/configobserver/featuregates/observe_featuregates_test.go @@ -50,7 +50,10 @@ func TestObserveFeatureFlags(t *testing.T) { "ExperimentalCriticalPodAnnotation=true", "RotateKubeletServerCertificate=true", "SupportPodPidsLimit=true", - "LocalStorageCapacityIsolation=false", + "TLSSecurityProfile=true", + "NodeDisruptionExclusion=true", + "ServiceNodeExclusion=true", + "LegacyNodeRoleBehavior=false", }, }, { @@ -60,7 +63,10 @@ func TestObserveFeatureFlags(t *testing.T) { "ExperimentalCriticalPodAnnotation=true", "RotateKubeletServerCertificate=true", "SupportPodPidsLimit=true", - "LocalStorageCapacityIsolation=false", + "TLSSecurityProfile=true", + "NodeDisruptionExclusion=true", + "ServiceNodeExclusion=true", + "LegacyNodeRoleBehavior=false", }, }, { @@ -127,7 +133,7 @@ func TestObserveFeatureFlags(t *testing.T) { t.Fatalf("unexpected error: %v", err) } if !reflect.DeepEqual(tc.expectedResult, actual) { - t.Errorf("%v", actual) + t.Errorf("Unexpected features gates\n got: %v\n expected: %v", actual, tc.expectedResult) } }) } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers.go new file mode 100644 index 0000000000..9771f749d7 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers.go @@ -0,0 +1,101 @@ +package encryption + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" + corev1 "k8s.io/client-go/kubernetes/typed/core/v1" + + configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" + configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1" + "github.com/openshift/library-go/pkg/operator/events" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" + + "github.com/openshift/library-go/pkg/operator/encryption/controllers" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/statemachine" +) + +type runner interface { + Run(stopCh <-chan struct{}) +} + +func NewControllers( + component string, + deployer statemachine.Deployer, + operatorClient operatorv1helpers.OperatorClient, + apiServerClient configv1client.APIServerInterface, + apiServerInformer configv1informers.APIServerInformer, + kubeInformersForNamespaces operatorv1helpers.KubeInformersForNamespaces, + secretsClient corev1.SecretsGetter, + discovery discovery.DiscoveryInterface, + eventRecorder events.Recorder, + dynamicClient dynamic.Interface, // temporary hack for in-process storage migration + encryptedGRs ...schema.GroupResource, +) (*Controllers, error) { + // avoid using the CachedSecretGetter as we need strong guarantees that our encryptionSecretSelector works + // otherwise we could see secrets from a different component (which will break our keyID invariants) + // this is fine in terms of performance since these controllers will be idle most of the time + // TODO: update the eventHandlers used by the controllers to ignore components that do not match their own + encryptionSecretSelector := metav1.ListOptions{LabelSelector: secrets.EncryptionKeySecretsLabel + "=" + component} + + return &Controllers{ + controllers: []runner{ + controllers.NewKeyController( + component, + deployer, + operatorClient, + apiServerClient, + apiServerInformer, + kubeInformersForNamespaces, + secretsClient, + encryptionSecretSelector, + eventRecorder, + encryptedGRs, + ), + controllers.NewStateController( + component, + deployer, + operatorClient, + kubeInformersForNamespaces, + secretsClient, + encryptionSecretSelector, + eventRecorder, + encryptedGRs, + ), + controllers.NewPruneController( + deployer, + operatorClient, + kubeInformersForNamespaces, + secretsClient, + encryptionSecretSelector, + eventRecorder, + encryptedGRs, + ), + controllers.NewMigrationController( + deployer, + operatorClient, + kubeInformersForNamespaces, + secretsClient, + encryptionSecretSelector, + eventRecorder, + encryptedGRs, + dynamicClient, + discovery, + ), + }, + }, nil +} + +type Controllers struct { + controllers []runner +} + +func (c *Controllers) Run(stopCh <-chan struct{}) { + for _, controller := range c.controllers { + con := controller // capture range variable + go con.Run(stopCh) + } + <-stopCh +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/controller.go new file mode 100644 index 0000000000..165f1e4212 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/controller.go @@ -0,0 +1,36 @@ +package controllers + +import ( + "k8s.io/client-go/tools/cache" + + "github.com/openshift/library-go/pkg/operator/encryption/statemachine" + "github.com/openshift/library-go/pkg/operator/management" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +func shouldRunEncryptionController(operatorClient operatorv1helpers.OperatorClient) (bool, error) { + operatorSpec, _, _, err := operatorClient.GetOperatorState() + if err != nil { + return false, err + } + + return management.IsOperatorManaged(operatorSpec.ManagementState), nil +} + +func setUpInformers( + deployer statemachine.Deployer, + operatorClient operatorv1helpers.OperatorClient, + kubeInformersForNamespaces operatorv1helpers.KubeInformersForNamespaces, + eventHandler cache.ResourceEventHandler, +) []cache.InformerSynced { + operatorInformer := operatorClient.Informer() + operatorInformer.AddEventHandler(eventHandler) + + managedSecretsInformer := kubeInformersForNamespaces.InformersFor("openshift-config-managed").Core().V1().Secrets().Informer() + managedSecretsInformer.AddEventHandler(eventHandler) + + return append([]cache.InformerSynced{ + operatorInformer.HasSynced, + managedSecretsInformer.HasSynced, + }, deployer.AddEventHandler(eventHandler)...) +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/helpers_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/helpers_test.go new file mode 100644 index 0000000000..a814cb57f2 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/helpers_test.go @@ -0,0 +1,21 @@ +package controllers + +import ( + "fmt" + "testing" + + corev1 "k8s.io/api/core/v1" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" +) + +func createEncryptionCfgSecret(t *testing.T, targetNs string, revision string, encryptionCfg *apiserverconfigv1.EncryptionConfiguration) *corev1.Secret { + t.Helper() + + s, err := encryptionconfig.ToSecret(targetNs, fmt.Sprintf("%s-%s", "encryption-config", revision), encryptionCfg) + if err != nil { + t.Fatal(err) + } + return s +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go new file mode 100644 index 0000000000..a5b9dc09a4 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller.go @@ -0,0 +1,371 @@ +package controllers + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "sort" + "strings" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + kyaml "k8s.io/apimachinery/pkg/util/yaml" + apiserverv1 "k8s.io/apiserver/pkg/apis/config/v1" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + + operatorv1 "github.com/openshift/api/operator/v1" + configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1" + configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1" + "github.com/openshift/library-go/pkg/operator/encryption/crypto" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/state" + "github.com/openshift/library-go/pkg/operator/encryption/statemachine" + "github.com/openshift/library-go/pkg/operator/events" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +const encWorkKey = "key" + +// encryptionSecretMigrationInterval determines how much time must pass after a key has been observed as +// migrated before a new key is created by the key minting controller. The new key's ID will be one +// greater than the last key's ID (the first key has a key ID of 1). +const encryptionSecretMigrationInterval = time.Hour * 24 * 7 // one week + +// keyController creates new keys if necessary. It +// * watches +// - secrets in openshift-config-managed +// - pods in target namespace +// - secrets in target namespace +// * computes a new, desired encryption config from encryption-config- +// and the existing keys in openshift-config-managed. +// * derives from the desired encryption config whether a new key is needed due to +// - encryption is being enabled via the API or +// - a new to-be-encrypted resource shows up or +// - the EncryptionType in the API does not match with the newest existing key or +// - based on time (once a week is the proposed rotation interval) or +// - an external reason given as a string in .encryption.reason of UnsupportedConfigOverrides. +// It then creates it. +// +// Note: the "based on time" reason for a new key is based on the annotation +// encryption.apiserver.operator.openshift.io/migrated-timestamp instead of +// the key secret's creationTimestamp because the clock is supposed to +// start when a migration has been finished, not when it begins. +type keyController struct { + operatorClient operatorv1helpers.OperatorClient + apiServerClient configv1client.APIServerInterface + + queue workqueue.RateLimitingInterface + eventRecorder events.Recorder + + preRunCachesSynced []cache.InformerSynced + + encryptedGRs []schema.GroupResource + + component string + encryptionSecretSelector metav1.ListOptions + + deployer statemachine.Deployer + secretClient corev1client.SecretsGetter +} + +func NewKeyController( + component string, + deployer statemachine.Deployer, + operatorClient operatorv1helpers.OperatorClient, + apiServerClient configv1client.APIServerInterface, + apiServerInformer configv1informers.APIServerInformer, + kubeInformersForNamespaces operatorv1helpers.KubeInformersForNamespaces, + secretClient corev1client.SecretsGetter, + encryptionSecretSelector metav1.ListOptions, + eventRecorder events.Recorder, + encryptedGRs []schema.GroupResource, +) *keyController { + c := &keyController{ + operatorClient: operatorClient, + apiServerClient: apiServerClient, + + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "EncryptionKeyController"), + eventRecorder: eventRecorder.WithComponentSuffix("encryption-key-controller"), // TODO unused + + encryptedGRs: encryptedGRs, + component: component, + + encryptionSecretSelector: encryptionSecretSelector, + deployer: deployer, + secretClient: secretClient, + } + + c.preRunCachesSynced = setUpInformers(deployer, operatorClient, kubeInformersForNamespaces, c.eventHandler()) + + apiServerInformer.Informer().AddEventHandler(c.eventHandler()) + c.preRunCachesSynced = append(c.preRunCachesSynced, apiServerInformer.Informer().HasSynced) + + return c +} + +func (c *keyController) sync() error { + if ready, err := shouldRunEncryptionController(c.operatorClient); err != nil || !ready { + return err // we will get re-kicked when the operator status updates + } + + configError := c.checkAndCreateKeys() + + // update failing condition + cond := operatorv1.OperatorCondition{ + Type: "EncryptionKeyControllerDegraded", + Status: operatorv1.ConditionFalse, + } + if configError != nil { + cond.Status = operatorv1.ConditionTrue + cond.Reason = "Error" + cond.Message = configError.Error() + } + if _, _, updateError := operatorv1helpers.UpdateStatus(c.operatorClient, operatorv1helpers.UpdateConditionFn(cond)); updateError != nil { + return updateError + } + + return configError +} + +func (c *keyController) checkAndCreateKeys() error { + currentMode, externalReason, err := c.getCurrentModeAndExternalReason() + if err != nil { + return err + } + + currentConfig, desiredEncryptionState, secretsFound, isProgressingReason, err := statemachine.GetEncryptionConfigAndState(c.deployer, c.secretClient, c.encryptionSecretSelector, c.encryptedGRs) + if err != nil { + return err + } + if len(isProgressingReason) > 0 { + c.queue.AddAfter(encWorkKey, 2*time.Minute) + return nil + } + + // avoid intended start of encryption + hasBeenOnBefore := currentConfig != nil || secretsFound + if currentMode == state.Identity && !hasBeenOnBefore { + return nil + } + + var ( + newKeyRequired bool + newKeyID uint64 + reasons []string + ) + + // note here that desiredEncryptionState is never empty because getDesiredEncryptionState + // fills up the state with all resources and set identity write key if write key secrets + // are missing. + + for _, grKeys := range desiredEncryptionState { + keyID, internalReason, ok := needsNewKey(grKeys, currentMode, externalReason, c.encryptedGRs) + if !ok { + continue + } + + newKeyRequired = true + nextKeyID := keyID + 1 + if newKeyID < nextKeyID { + newKeyID = nextKeyID + } + reasons = append(reasons, internalReason) + } + + if !newKeyRequired { + return nil + } + + sort.Sort(sort.StringSlice(reasons)) + internalReason := strings.Join(reasons, ", ") + keySecret, err := c.generateKeySecret(newKeyID, currentMode, internalReason, externalReason) + if err != nil { + return fmt.Errorf("failed to create key: %v", err) + } + _, createErr := c.secretClient.Secrets("openshift-config-managed").Create(keySecret) + if errors.IsAlreadyExists(createErr) { + return c.validateExistingSecret(keySecret, newKeyID) + } + return createErr +} + +func (c *keyController) validateExistingSecret(keySecret *corev1.Secret, keyID uint64) error { + actualKeySecret, err := c.secretClient.Secrets("openshift-config-managed").Get(keySecret.Name, metav1.GetOptions{}) + if err != nil { + return err + } + + actualKeyID, ok := state.NameToKeyID(actualKeySecret.Name) + if !ok || actualKeyID != keyID { + // TODO we can just get stuck in degraded here ... + return fmt.Errorf("secret %s has an invalid name, new keys cannot be created for encryption target", keySecret.Name) + } + + if _, err := secrets.ToKeyState(actualKeySecret); err != nil { + return fmt.Errorf("secret %s is invalid, new keys cannot be created for encryption target", keySecret.Name) + } + + return nil // we made this key earlier +} + +func (c *keyController) generateKeySecret(keyID uint64, currentMode state.Mode, internalReason, externalReason string) (*corev1.Secret, error) { + bs := crypto.ModeToNewKeyFunc[currentMode]() + ks := state.KeyState{ + Key: apiserverv1.Key{ + Name: fmt.Sprintf("%d", keyID), + Secret: base64.StdEncoding.EncodeToString(bs), + }, + Mode: currentMode, + InternalReason: internalReason, + ExternalReason: externalReason, + } + return secrets.FromKeyState(c.component, ks) +} + +func (c *keyController) getCurrentModeAndExternalReason() (state.Mode, string, error) { + apiServer, err := c.apiServerClient.Get("cluster", metav1.GetOptions{}) + if err != nil { + return "", "", err + } + + operatorSpec, _, _, err := c.operatorClient.GetOperatorState() + if err != nil { + return "", "", err + } + + // TODO make this un-settable once set + // ex: we could require the tech preview no upgrade flag to be set before we will honor this field + type unsupportedEncryptionConfig struct { + Encryption struct { + Reason string `json:"reason"` + } `json:"encryption"` + } + encryptionConfig := &unsupportedEncryptionConfig{} + if raw := operatorSpec.UnsupportedConfigOverrides.Raw; len(raw) > 0 { + jsonRaw, err := kyaml.ToJSON(raw) + if err != nil { + klog.Warning(err) + // maybe it's just json + jsonRaw = raw + } + if err := json.Unmarshal(jsonRaw, encryptionConfig); err != nil { + return "", "", err + } + } + + reason := encryptionConfig.Encryption.Reason + switch currentMode := state.Mode(apiServer.Spec.Encryption.Type); currentMode { + case state.AESCBC, state.Identity: // secretbox is disabled for now + return currentMode, reason, nil + case "": // unspecified means use the default (which can change over time) + return state.DefaultMode, reason, nil + default: + return "", "", fmt.Errorf("unknown encryption mode configured: %s", currentMode) + } +} + +// TODO unit tests +func needsNewKey(grKeys state.GroupResourceState, currentMode state.Mode, externalReason string, encryptedGRs []schema.GroupResource) (uint64, string, bool) { + // we always need to have some encryption keys unless we are turned off + if len(grKeys.ReadKeys) == 0 { + return 0, "no-secrets", currentMode != state.Identity + } + + latestKey := grKeys.ReadKeys[0] + latestKeyID, ok := state.NameToKeyID(latestKey.Key.Name) + if !ok { + return latestKeyID, "invalid-secret", true + } + + // if latest secret has been deleted, we will never be able to migrate to that key. + if !latestKey.Backed { + return latestKeyID, "missing-secret", true + } + + // if the length of read secrets is more than one (i.e. we have more than just the write key), + // then we haven't successfully migrated and removed old keys so you should wait before generating more keys. + if len(grKeys.ReadKeys) > 1 { + return 0, "", false + } + + // we have not migrated the latest key, do nothing until that is complete + if allMigrated, _, _ := state.MigratedFor(encryptedGRs, latestKey); !allMigrated { + return 0, "", false + } + + // if the most recent secret was encrypted in a mode different than the current mode, we need to generate a new key + if latestKey.Mode != currentMode { + return latestKeyID, "new-mode", true + } + + // if the most recent secret turned off encryption and we want to keep it that way, do nothing + if latestKey.Mode == state.Identity && currentMode == state.Identity { + return 0, "", false + } + + // if the most recent secret has a different external reason than the current reason, we need to generate a new key + if latestKey.ExternalReason != externalReason && len(externalReason) != 0 { + return latestKeyID, "new-external-reason", true + } + + // we check for encryptionSecretMigratedTimestamp set by migration controller to determine when migration completed + // this also generates back pressure for key rotation when migration takes a long time or was recently completed + return latestKeyID, "timestamp-too-old", time.Since(latestKey.Migrated.Timestamp) > encryptionSecretMigrationInterval +} + +func (c *keyController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Infof("Starting EncryptionKeyController") + defer klog.Infof("Shutting down EncryptionKeyController") + if !cache.WaitForCacheSync(stopCh, c.preRunCachesSynced...) { + utilruntime.HandleError(fmt.Errorf("caches did not sync")) + return + } + + // only start one worker + go wait.Until(c.runWorker, time.Second, stopCh) + + <-stopCh +} + +func (c *keyController) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *keyController) processNextWorkItem() bool { + dsKey, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(dsKey) + + err := c.sync() + if err == nil { + c.queue.Forget(dsKey) + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with: %v", dsKey, err)) + c.queue.AddRateLimited(dsKey) + + return true +} + +func (c *keyController) eventHandler() cache.ResourceEventHandler { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.queue.Add(encWorkKey) }, + UpdateFunc: func(old, new interface{}) { c.queue.Add(encWorkKey) }, + DeleteFunc: func(obj interface{}) { c.queue.Add(encWorkKey) }, + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller_test.go new file mode 100644 index 0000000000..ed18425456 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/key_controller_test.go @@ -0,0 +1,323 @@ +package controllers + +import ( + "errors" + "fmt" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/diff" + "k8s.io/client-go/kubernetes/fake" + clientgotesting "k8s.io/client-go/testing" + + configv1 "github.com/openshift/api/config/v1" + operatorv1 "github.com/openshift/api/operator/v1" + configv1clientfake "github.com/openshift/client-go/config/clientset/versioned/fake" + configv1informers "github.com/openshift/client-go/config/informers/externalversions" + encryptiondeployer "github.com/openshift/library-go/pkg/operator/encryption/deployer" + encryptiontesting "github.com/openshift/library-go/pkg/operator/encryption/testing" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +func TestKeyController(t *testing.T) { + apiServerAesCBC := []runtime.Object{&configv1.APIServer{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster"}, + Spec: configv1.APIServerSpec{ + Encryption: configv1.APIServerEncryption{ + Type: "aescbc", + }, + }, + }} + + scenarios := []struct { + name string + initialObjects []runtime.Object + apiServerObjects []runtime.Object + encryptionSecretSelector metav1.ListOptions + targetNamespace string + targetGRs []schema.GroupResource + // expectedActions holds actions to be verified in the form of "verb:resource:namespace" + expectedActions []string + validateFunc func(ts *testing.T, actions []clientgotesting.Action, targetNamespace string, targetGRs []schema.GroupResource) + validateOperatorClientFunc func(ts *testing.T, operatorClient v1helpers.OperatorClient) + expectedError error + }{ + { + name: "no apiservers config", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + targetNamespace: "kms", + initialObjects: []runtime.Object{}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, targetNamespace string, targetGRs []schema.GroupResource) { + }, + expectedError: fmt.Errorf(`apiservers.config.openshift.io "cluster" not found`), + expectedActions: []string{}, + }, + + { + name: "no pod", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + targetNamespace: "kms", + initialObjects: []runtime.Object{}, + apiServerObjects: []runtime.Object{&configv1.APIServer{ObjectMeta: metav1.ObjectMeta{Name: "cluster"}}}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, targetNamespace string, targetGRs []schema.GroupResource) { + }, + expectedActions: []string{"list:pods:kms"}, + }, + + { + name: "encryption disabled", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + targetNamespace: "kms", + initialObjects: []runtime.Object{encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1")}, + apiServerObjects: []runtime.Object{&configv1.APIServer{ObjectMeta: metav1.ObjectMeta{Name: "cluster"}}}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, targetNamespace string, targetGRs []schema.GroupResource) { + }, + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed"}, + }, + + // Assumes a clean slate, that is, there are no previous resources in the system. + // It expects that a secret resource with an appropriate key, name and labels will be created. + { + name: "checks if a secret with AES256 key for core/secret is created", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + targetNamespace: "kms", + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "create:secrets:openshift-config-managed"}, + initialObjects: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + }, + apiServerObjects: []runtime.Object{&configv1.APIServer{ + ObjectMeta: metav1.ObjectMeta{Name: "cluster"}, + Spec: configv1.APIServerSpec{ + Encryption: configv1.APIServerEncryption{ + Type: "aescbc", + }, + }, + }}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, targetNamespace string, targetGRs []schema.GroupResource) { + wasSecretValidated := false + for _, action := range actions { + if action.Matches("create", "secrets") { + createAction := action.(clientgotesting.CreateAction) + actualSecret := createAction.GetObject().(*corev1.Secret) + expectedSecret := encryptiontesting.CreateEncryptionKeySecretWithKeyFromExistingSecret(targetNamespace, []schema.GroupResource{}, 1, actualSecret) + if !equality.Semantic.DeepEqual(actualSecret, expectedSecret) { + ts.Errorf(diff.ObjectDiff(expectedSecret, actualSecret)) + } + if err := encryptiontesting.ValidateEncryptionKey(actualSecret); err != nil { + ts.Error(err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + }, + }, + + { + name: "no-op when a valid write key exists, but is not migrated", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialObjects: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 7, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + apiServerObjects: apiServerAesCBC, + targetNamespace: "kms", + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed"}, + }, + + { + name: "no-op when a valid write key exists, is migrated, but not expired", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialObjects: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 7, []byte("61def964fb967f5d7c44a2af8dab6865"), time.Now()), + }, + apiServerObjects: apiServerAesCBC, + targetNamespace: "kms", + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed"}, + }, + + { + name: "creates a new write key because previous one is migrated, but has no migration timestamp", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialObjects: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 7, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + apiServerObjects: apiServerAesCBC, + targetNamespace: "kms", + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "create:secrets:openshift-config-managed"}, + }, + + { + name: "creates a new write key because the previous one expired", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialObjects: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 5, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + apiServerObjects: apiServerAesCBC, + targetNamespace: "kms", + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "create:secrets:openshift-config-managed"}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, targetNamespace string, targetGRs []schema.GroupResource) { + wasSecretValidated := false + for _, action := range actions { + if action.Matches("create", "secrets") { + createAction := action.(clientgotesting.CreateAction) + actualSecret := createAction.GetObject().(*corev1.Secret) + expectedSecret := encryptiontesting.CreateEncryptionKeySecretWithKeyFromExistingSecret(targetNamespace, []schema.GroupResource{}, 6, actualSecret) + expectedSecret.Annotations["encryption.apiserver.operator.openshift.io/internal-reason"] = "timestamp-too-old" + if !equality.Semantic.DeepEqual(actualSecret, expectedSecret) { + ts.Errorf(diff.ObjectDiff(expectedSecret, actualSecret)) + } + if err := encryptiontesting.ValidateEncryptionKey(actualSecret); err != nil { + ts.Error(err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + }, + }, + + { + name: "no-op when the previous key was migrated and the current one is valid but hasn't been observed", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialObjects: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 5, []byte("61def964fb967f5d7c44a2af8dab6865")), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 6, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + apiServerObjects: apiServerAesCBC, + targetNamespace: "kms", + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed"}, + }, + + { + name: "degraded a secret with invalid key exists", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialObjects: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("")), + }, + apiServerObjects: apiServerAesCBC, + targetNamespace: "kms", + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "create:secrets:openshift-config-managed", "get:secrets:openshift-config-managed"}, + validateOperatorClientFunc: func(ts *testing.T, operatorClient v1helpers.OperatorClient) { + expectedCondition := operatorv1.OperatorCondition{ + Type: "EncryptionKeyControllerDegraded", + Status: "True", + Reason: "Error", + Message: "secret encryption-key-kms-1 is invalid, new keys cannot be created for encryption target", + } + encryptiontesting.ValidateOperatorClientConditions(ts, operatorClient, []operatorv1.OperatorCondition{expectedCondition}) + }, + expectedError: errors.New("secret encryption-key-kms-1 is invalid, new keys cannot be created for encryption target"), + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + // setup + fakeOperatorClient := v1helpers.NewFakeStaticPodOperatorClient( + &operatorv1.StaticPodOperatorSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: operatorv1.Managed, + }, + }, + &operatorv1.StaticPodOperatorStatus{ + OperatorStatus: operatorv1.OperatorStatus{ + // we need to set up proper conditions before the test starts because + // the controller calls UpdateStatus which calls UpdateOperatorStatus method which is unsupported (fake client) and throws an exception + Conditions: []operatorv1.OperatorCondition{ + { + Type: "EncryptionKeyControllerDegraded", + Status: "False", + }, + }, + }, + NodeStatuses: []operatorv1.NodeStatus{ + {NodeName: "node-1"}, + }, + }, + nil, + nil, + ) + + fakeKubeClient := fake.NewSimpleClientset(scenario.initialObjects...) + eventRecorder := events.NewRecorder(fakeKubeClient.CoreV1().Events(scenario.targetNamespace), "test-encryptionKeyController", &corev1.ObjectReference{}) + // pass informer for + // - target namespace: pods and secrets + // - openshift-config-managed: secrets + // note that the informer factory is not used in the test - it's only needed to create the controller + kubeInformers := v1helpers.NewKubeInformersForNamespaces(fakeKubeClient, "openshift-config-managed", scenario.targetNamespace) + fakeSecretClient := fakeKubeClient.CoreV1() + fakePodClient := fakeKubeClient.CoreV1() + fakeConfigClient := configv1clientfake.NewSimpleClientset(scenario.apiServerObjects...) + fakeApiServerClient := fakeConfigClient.ConfigV1().APIServers() + fakeApiServerInformer := configv1informers.NewSharedInformerFactory(fakeConfigClient, time.Minute).Config().V1().APIServers() + + deployer, err := encryptiondeployer.NewStaticPodDeployer(scenario.targetNamespace, kubeInformers, nil, fakePodClient, fakeSecretClient, fakeOperatorClient) + if err != nil { + t.Fatal(err) + } + + target := NewKeyController(scenario.targetNamespace, deployer, fakeOperatorClient, fakeApiServerClient, fakeApiServerInformer, kubeInformers, fakeSecretClient, scenario.encryptionSecretSelector, eventRecorder, scenario.targetGRs) + + // act + err = target.sync() + + // validate + if err == nil && scenario.expectedError != nil { + t.Fatal("expected to get an error from sync() method") + } + if err != nil && scenario.expectedError == nil { + t.Fatal(err) + } + if err != nil && scenario.expectedError != nil && err.Error() != scenario.expectedError.Error() { + t.Fatalf("unexpected error returned = %v, expected = %v", err, scenario.expectedError) + } + if err := encryptiontesting.ValidateActionsVerbs(fakeKubeClient.Actions(), scenario.expectedActions); err != nil { + t.Fatalf("incorrect action(s) detected: %v", err) + } + if scenario.validateFunc != nil { + scenario.validateFunc(t, fakeKubeClient.Actions(), scenario.targetNamespace, scenario.targetGRs) + } + if scenario.validateOperatorClientFunc != nil { + scenario.validateOperatorClientFunc(t, fakeOperatorClient) + } + }) + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/migration_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/migration_controller.go new file mode 100644 index 0000000000..3ae9ec13e0 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/migration_controller.go @@ -0,0 +1,410 @@ +package controllers + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + "strings" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/discovery" + "k8s.io/client-go/dynamic" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/pager" + "k8s.io/client-go/util/retry" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/state" + "github.com/openshift/library-go/pkg/operator/encryption/statemachine" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +const migrationWorkKey = "key" + +// The migrationController controller migrates resources to a new write key +// and annotated the write key secret afterwards with the migrated GRs. It +// +// * watches pods and secrets in +// * watches secrets in openshift-config-manager +// * computes a new, desired encryption config from encryption-config- +// and the existing keys in openshift-config-managed. +// * compares desired with current target config and stops when they differ +// * checks the write-key secret whether +// - encryption.apiserver.operator.openshift.io/migrated-timestamp annotation +// is missing or +// - a write-key for a resource does not show up in the +// encryption.apiserver.operator.openshift.io/migrated-resources And then +// starts a migration job (currently in-place synchronously, soon with the upstream migration tool) +// * updates the encryption.apiserver.operator.openshift.io/migrated-timestamp and +// encryption.apiserver.operator.openshift.io/migrated-resources annotations on the +// current write-key secrets. +type migrationController struct { + operatorClient operatorv1helpers.OperatorClient + + queue workqueue.RateLimitingInterface + eventRecorder events.Recorder + + preRunCachesSynced []cache.InformerSynced + + encryptedGRs []schema.GroupResource + + encryptionSecretSelector metav1.ListOptions + + secretClient corev1client.SecretsGetter + + deployer statemachine.Deployer + + dynamicClient dynamic.Interface + discoveryClient discovery.ServerResourcesInterface +} + +func NewMigrationController( + deployer statemachine.Deployer, + operatorClient operatorv1helpers.OperatorClient, + kubeInformersForNamespaces operatorv1helpers.KubeInformersForNamespaces, + secretClient corev1client.SecretsGetter, + encryptionSecretSelector metav1.ListOptions, + eventRecorder events.Recorder, + encryptedGRs []schema.GroupResource, + dynamicClient dynamic.Interface, // temporary hack + discoveryClient discovery.ServerResourcesInterface, +) *migrationController { + c := &migrationController{ + operatorClient: operatorClient, + + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "EncryptionMigrationController"), + eventRecorder: eventRecorder.WithComponentSuffix("encryption-migration-controller"), + + encryptedGRs: encryptedGRs, + + encryptionSecretSelector: encryptionSecretSelector, + secretClient: secretClient, + deployer: deployer, + dynamicClient: dynamicClient, + discoveryClient: discoveryClient, + } + + c.preRunCachesSynced = setUpInformers(deployer, operatorClient, kubeInformersForNamespaces, c.eventHandler()) + + return c +} + +func (c *migrationController) sync() error { + if ready, err := shouldRunEncryptionController(c.operatorClient); err != nil || !ready { + return err // we will get re-kicked when the operator status updates + } + + resetProgressing, configError := c.migrateKeysIfNeededAndRevisionStable() + + // update failing condition + degraded := operatorv1.OperatorCondition{ + Type: "EncryptionMigrationControllerDegraded", + Status: operatorv1.ConditionFalse, + } + if configError != nil { + degraded.Status = operatorv1.ConditionTrue + degraded.Reason = "Error" + degraded.Message = configError.Error() + } + + updateFuncs := []operatorv1helpers.UpdateStatusFunc{operatorv1helpers.UpdateConditionFn(degraded)} + + // reset progressing condition + if resetProgressing { + progressing := operatorv1.OperatorCondition{ + Type: "EncryptionMigrationControllerProgressing", + Status: operatorv1.ConditionFalse, + } + updateFuncs = append(updateFuncs, operatorv1helpers.UpdateConditionFn(progressing)) + } + if _, _, updateError := operatorv1helpers.UpdateStatus(c.operatorClient, updateFuncs...); updateError != nil { + return updateError + } + + return configError +} + +func (c *migrationController) setProgressing(reason, message string, args ...interface{}) error { + // update progressing condition + progressing := operatorv1.OperatorCondition{ + Type: "EncryptionMigrationControllerProgressing", + Status: operatorv1.ConditionTrue, + Reason: reason, + Message: fmt.Sprintf(message, args...), + } + + _, _, err := operatorv1helpers.UpdateStatus(c.operatorClient, operatorv1helpers.UpdateConditionFn(progressing)) + return err +} + +// TODO doc +func (c *migrationController) migrateKeysIfNeededAndRevisionStable() (resetProgressing bool, err error) { + // no storage migration during revision changes + currentEncryptionConfig, desiredEncryptionState, _, isTransitionalReason, err := statemachine.GetEncryptionConfigAndState(c.deployer, c.secretClient, c.encryptionSecretSelector, c.encryptedGRs) + if err != nil { + return false, err + } + if currentEncryptionConfig == nil || len(isTransitionalReason) > 0 { + c.queue.AddAfter(migrationWorkKey, 2*time.Minute) + return true, nil + } + + // no storage migration until config is stable + desiredEncryptedConfig := encryptionconfig.FromEncryptionState(desiredEncryptionState) + if !reflect.DeepEqual(currentEncryptionConfig.Resources, desiredEncryptedConfig.Resources) { + c.queue.AddAfter(migrationWorkKey, 2*time.Minute) + return true, nil // retry in a little while but do not go degraded + } + + // all API servers have converged onto a single revision that matches our desired overall encryption state + // now we know that it is safe to attempt key migrations + // we never want to migrate during an intermediate state because that could lead to one API server + // using a write key that another API server has not observed + // this could lead to etcd storing data that not all API servers can decrypt + for gr, grActualKeys := range encryptionconfig.ToEncryptionState(currentEncryptionConfig) { + if !grActualKeys.HasWriteKey() { + continue // no write key to migrate to + } + + writeSecret, err := findSecretForKeyWithClient(grActualKeys.WriteKey, c.secretClient, c.encryptionSecretSelector) + if err != nil { + return true, err + } + ok := writeSecret != nil + if !ok { // make sure this is a fully observed write key + klog.V(4).Infof("write key %s for group=%s resource=%s not fully observed", grActualKeys.WriteKey.Key.Name, groupToHumanReadable(gr), gr.Resource) + continue + } + + if needsMigration(writeSecret, gr) { + // storage migration takes a long time so we expose that via a distinct status change + if err := c.setProgressing(strings.Title(groupToHumanReadable(gr))+strings.Title(gr.Resource), "migrating resource %s.%s to new write key", groupToHumanReadable(gr), gr.Resource); err != nil { + return false, err + } + + if err := c.runStorageMigration(gr); err != nil { + return false, err + } + + // update secret annotations + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + s, err := c.secretClient.Secrets(writeSecret.Namespace).Get(writeSecret.Name, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("failed to get key secret %s/%s: %v", writeSecret.Namespace, writeSecret.Name, err) + } + + changed, err := setResourceMigrated(gr, s) + if !changed { + return nil + } + + _, _, updateErr := resourceapply.ApplySecret(c.secretClient, c.eventRecorder, s) + return updateErr + }); err != nil { + return false, err + } + } + } + + // if we reach this, all migration went fine and we can reset progressing condition + return true, nil +} + +func findSecretForKeyWithClient(key state.KeyState, secretClient corev1client.SecretsGetter, encryptionSecretSelector metav1.ListOptions) (*corev1.Secret, error) { + if len(key.Key.Name) == 0 { + return nil, nil + } + + secretList, err := secretClient.Secrets("openshift-config-managed").List(encryptionSecretSelector) + if err != nil { + return nil, err + } + + for _, secret := range secretList.Items { + sKeyAndMode, err := secrets.ToKeyState(&secret) + if err != nil { + // invalid + continue + } + if state.EqualKeyAndEqualID(&sKeyAndMode, &key) { + return &secret, nil + } + } + + return nil, nil +} + +func setResourceMigrated(gr schema.GroupResource, s *corev1.Secret) (bool, error) { + migratedGRs := secrets.MigratedGroupResources{} + if existing, found := s.Annotations[secrets.EncryptionSecretMigratedResources]; found { + if err := json.Unmarshal([]byte(existing), &migratedGRs); err != nil { + // ignore error and just start fresh, causing some more migration at worst + migratedGRs = secrets.MigratedGroupResources{} + } + } + + alreadyMigrated := false + for _, existingGR := range migratedGRs.Resources { + if existingGR == gr { + alreadyMigrated = true + break + } + } + + // update timestamp, if missing or first migration of gr + if _, found := s.Annotations[secrets.EncryptionSecretMigratedTimestamp]; found && alreadyMigrated { + return false, nil + } + if s.Annotations == nil { + s.Annotations = map[string]string{} + } + s.Annotations[secrets.EncryptionSecretMigratedTimestamp] = time.Now().Format(time.RFC3339) + + // update resource list + if !alreadyMigrated { + migratedGRs.Resources = append(migratedGRs.Resources, gr) + bs, err := json.Marshal(migratedGRs) + if err != nil { + return false, fmt.Errorf("failed to marshal %s annotation value %#v for key secret %s/%s", secrets.EncryptionSecretMigratedResources, migratedGRs, s.Namespace, s.Name) + } + s.Annotations[secrets.EncryptionSecretMigratedResources] = string(bs) + } + + return true, nil +} + +func needsMigration(secret *corev1.Secret, gr schema.GroupResource) bool { + ks, err := secrets.ToKeyState(secret) + if err != nil { + klog.Infof("invalid key secret %s/%s", secret.Namespace, secret.Name) + return false + } + alreadyMigrated, _, _ := state.MigratedFor([]schema.GroupResource{gr}, ks) + return !alreadyMigrated +} + +func (c *migrationController) runStorageMigration(gr schema.GroupResource) error { + version, err := c.getVersion(gr) + if err != nil { + return err + } + d := c.dynamicClient.Resource(gr.WithVersion(version)) + + var errs []error + + listPager := pager.New(pager.SimplePageFunc(func(opts metav1.ListOptions) (runtime.Object, error) { + allResource, err := d.List(opts) + if err != nil { + return nil, err // TODO this can wedge on resource expired errors with large overall list + } + for _, obj := range allResource.Items { // TODO parallelize for-loop + _, updateErr := d.Namespace(obj.GetNamespace()).Update(&obj, metav1.UpdateOptions{}) + errs = append(errs, updateErr) + } + allResource.Items = nil // do not accumulate items, this fakes the visitor pattern + return allResource, nil // leave the rest of the list intact to preserve continue token + })) + + listPager.FullListIfExpired = false // prevent memory explosion from full list + _, listErr := listPager.List(context.TODO(), metav1.ListOptions{}) + errs = append(errs, listErr) + + return utilerrors.FilterOut(utilerrors.NewAggregate(errs), errors.IsNotFound, errors.IsConflict) +} + +func (c *migrationController) getVersion(gr schema.GroupResource) (string, error) { + resourceLists, discoveryErr := c.discoveryClient.ServerPreferredResources() // safe to ignore error + for _, resourceList := range resourceLists { + groupVersion, err := schema.ParseGroupVersion(resourceList.GroupVersion) + if err != nil { + return "", err + } + if groupVersion.Group != gr.Group { + continue + } + for _, resource := range resourceList.APIResources { + if (len(resource.Group) == 0 || resource.Group == gr.Group) && resource.Name == gr.Resource { + if len(resource.Version) > 0 { + return resource.Version, nil + } + return groupVersion.Version, nil + } + } + } + return "", fmt.Errorf("failed to find version for %s, discoveryErr=%v", gr, discoveryErr) +} + +func (c *migrationController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Infof("Starting EncryptionMigrationController") + defer klog.Infof("Shutting down EncryptionMigrationController") + if !cache.WaitForCacheSync(stopCh, c.preRunCachesSynced...) { + utilruntime.HandleError(fmt.Errorf("caches did not sync")) + return + } + + // only start one worker + go wait.Until(c.runWorker, time.Second, stopCh) + + <-stopCh +} + +func (c *migrationController) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *migrationController) processNextWorkItem() bool { + dsKey, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(dsKey) + + err := c.sync() + if err == nil { + c.queue.Forget(dsKey) + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with: %v", dsKey, err)) + c.queue.AddRateLimited(dsKey) + + return true +} + +func (c *migrationController) eventHandler() cache.ResourceEventHandler { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.queue.Add(migrationWorkKey) }, + UpdateFunc: func(old, new interface{}) { c.queue.Add(migrationWorkKey) }, + DeleteFunc: func(obj interface{}) { c.queue.Add(migrationWorkKey) }, + } +} + +// groupToHumanReadable extracts a group from gr and makes it more readable, for example it converts an empty group to "core" +// Note: do not use it to get resources from the server only when printing to a log file +func groupToHumanReadable(gr schema.GroupResource) string { + group := gr.Group + if len(group) == 0 { + group = "core" + } + return group +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/migration_controller_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/migration_controller_test.go new file mode 100644 index 0000000000..88678a977a --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/migration_controller_test.go @@ -0,0 +1,469 @@ +package controllers + +import ( + "encoding/json" + "fmt" + "strings" + "testing" + + openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/version" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + "k8s.io/client-go/discovery" + dynamicfakeclient "k8s.io/client-go/dynamic/fake" + "k8s.io/client-go/kubernetes/fake" + clientgotesting "k8s.io/client-go/testing" + + operatorv1 "github.com/openshift/api/operator/v1" + encryptiondeployer "github.com/openshift/library-go/pkg/operator/encryption/deployer" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + encryptiontesting "github.com/openshift/library-go/pkg/operator/encryption/testing" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +func TestMigrationController(t *testing.T) { + scenarios := []struct { + name string + initialResources []runtime.Object + initialSecrets []*corev1.Secret + encryptionSecretSelector metav1.ListOptions + targetNamespace string + targetGRs []schema.GroupResource + targetAPIResources []metav1.APIResource + // expectedActions holds actions to be verified in the form of "verb:resource:namespace" + expectedActions []string + validateFunc func(ts *testing.T, actionsKube []clientgotesting.Action, actionsDynamic []clientgotesting.Action, initialSecrets []*corev1.Secret, targetGRs []schema.GroupResource, unstructuredObjs []runtime.Object) + validateOperatorClientFunc func(ts *testing.T, operatorClient v1helpers.OperatorClient) + expectedError error + }{ + { + name: "no config => nothing happens", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + {Group: "", Resource: "configmaps"}, + }, + targetAPIResources: []metav1.APIResource{ + { + Name: "secrets", + Namespaced: true, + Group: "", + Version: "v1", + }, + { + Name: "configmaps", + Namespaced: true, + Group: "", + Version: "v1", + }, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + func() runtime.Object { + cm := createConfigMap("cm-1", "os") + cm.Kind = "ConfigMap" + cm.APIVersion = corev1.SchemeGroupVersion.String() + return cm + }(), + func() runtime.Object { + cm := createConfigMap("cm-2", "os") + cm.Kind = "ConfigMap" + cm.APIVersion = corev1.SchemeGroupVersion.String() + return cm + }(), + }, + initialSecrets: nil, + expectedActions: []string{ + "list:pods:kms", + "get:secrets:kms", + "list:secrets:openshift-config-managed", + }, + }, + + { + name: "a happy path scenario that tests resources encryption and secrets annotation", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + {Group: "", Resource: "configmaps"}, + }, + targetAPIResources: []metav1.APIResource{ + { + Name: "secrets", + Namespaced: true, + Group: "", + Version: "v1", + }, + { + Name: "configmaps", + Namespaced: true, + Group: "", + Version: "v1", + }, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + func() runtime.Object { + cm := createConfigMap("cm-1", "os") + cm.Kind = "ConfigMap" + cm.APIVersion = corev1.SchemeGroupVersion.String() + return cm + }(), + func() runtime.Object { + cm := createConfigMap("cm-2", "os") + cm.Kind = "ConfigMap" + cm.APIVersion = corev1.SchemeGroupVersion.String() + return cm + }(), + }, + initialSecrets: []*corev1.Secret{ + func() *corev1.Secret { + s := encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("71ea7c91419a68fd1224f88d50316b4e")) + s.Kind = "Secret" + s.APIVersion = corev1.SchemeGroupVersion.String() + return s + }(), + func() *corev1.Secret { + keysResForSecrets := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "1", + Secret: "NzFlYTdjOTE0MTlhNjhmZDEyMjRmODhkNTAzMTZiNGU=", + }, + }, + } + keysResForConfigMaps := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "configmaps", + Keys: []apiserverconfigv1.Key{ + { + Name: "1", + Secret: "NzFlYTdjOTE0MTlhNjhmZDEyMjRmODhkNTAzMTZiNGU=", + }, + }, + } + + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysResForConfigMaps, keysResForSecrets}) + ecs := createEncryptionCfgSecret(t, "kms", "1", ec) + ecs.APIVersion = corev1.SchemeGroupVersion.String() + + return ecs + }(), + func() *corev1.Secret { + s := &corev1.Secret{} + s.Name = "s-in-abc" + s.Namespace = "abc-ns" + s.Kind = "Secret" + s.APIVersion = corev1.SchemeGroupVersion.String() + return s + }(), + }, + expectedActions: []string{ + "list:pods:kms", + "get:secrets:kms", + "list:secrets:openshift-config-managed", + "list:secrets:openshift-config-managed", + "get:secrets:openshift-config-managed", + "get:secrets:openshift-config-managed", + "update:secrets:openshift-config-managed", + "create:events:operator", + "list:secrets:openshift-config-managed", + "get:secrets:openshift-config-managed", + "get:secrets:openshift-config-managed", + "update:secrets:openshift-config-managed", + "create:events:operator", + }, + validateFunc: func(ts *testing.T, actionsKube []clientgotesting.Action, actionsDynamic []clientgotesting.Action, initialSecrets []*corev1.Secret, targetGRs []schema.GroupResource, unstructuredObjs []runtime.Object) { + // validate if the secrets were properly annotated + validateSecretsWereAnnotated(ts, []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, actionsKube, []*corev1.Secret{initialSecrets[0]}) + // validate if the resources were "encrypted" + validateMigratedResources(ts, actionsDynamic, unstructuredObjs, targetGRs) + }, + validateOperatorClientFunc: func(ts *testing.T, operatorClient v1helpers.OperatorClient) { + expectedConditions := []operatorv1.OperatorCondition{ + { + Type: "EncryptionMigrationControllerDegraded", + Status: "False", + }, + { + Type: "EncryptionMigrationControllerProgressing", + Status: "False", + }, + } + // TODO: test sequence of condition changes, not only the end result + encryptiontesting.ValidateOperatorClientConditions(ts, operatorClient, expectedConditions) + }, + }, + + // TODO: add more tests for not so happy paths + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + // setup + fakeOperatorClient := v1helpers.NewFakeStaticPodOperatorClient( + &operatorv1.StaticPodOperatorSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: operatorv1.Managed, + }, + }, + &operatorv1.StaticPodOperatorStatus{ + OperatorStatus: operatorv1.OperatorStatus{ + Conditions: []operatorv1.OperatorCondition{ + { + Type: "EncryptionMigrationControllerDegraded", + Status: "False", + }, + { + Type: "EncryptionMigrationControllerProgressing", + Status: operatorv1.ConditionFalse, + }, + }, + }, + NodeStatuses: []operatorv1.NodeStatus{ + {NodeName: "node-1"}, + }, + }, + nil, + nil, + ) + + allResources := []runtime.Object{} + allResources = append(allResources, scenario.initialResources...) + for _, initialSecret := range scenario.initialSecrets { + allResources = append(allResources, initialSecret) + } + fakeKubeClient := fake.NewSimpleClientset(allResources...) + eventRecorder := events.NewRecorder(fakeKubeClient.CoreV1().Events("operator"), "test-encryptionKeyController", &corev1.ObjectReference{}) + // we pass "openshift-config-managed" and $targetNamespace ns because the controller creates an informer for secrets in that namespace. + // note that the informer factory is not used in the test - it's only needed to create the controller + kubeInformers := v1helpers.NewKubeInformersForNamespaces(fakeKubeClient, "openshift-config-managed", scenario.targetNamespace) + fakeSecretClient := fakeKubeClient.CoreV1() + + // let dynamic client know about the resources we want to encrypt + resourceRequiresEncyrptionFunc := func(kind string) bool { + if len(kind) == 0 { + return false + } + for _, gr := range scenario.targetGRs { + if strings.HasPrefix(gr.Resource, strings.ToLower(kind)) { + return true + } + } + return false + } + scheme := runtime.NewScheme() + unstructuredObjs := []runtime.Object{} + for _, rawObject := range allResources { + rawUnstructured, err := runtime.DefaultUnstructuredConverter.ToUnstructured(rawObject.DeepCopyObject()) + if err != nil { + t.Fatal(err) + } + unstructuredObj := &unstructured.Unstructured{Object: rawUnstructured} + if resourceRequiresEncyrptionFunc(unstructuredObj.GetKind()) { + unstructuredObjs = append(unstructuredObjs, unstructuredObj) + } + } + fakeDynamicClient := dynamicfakeclient.NewSimpleDynamicClient(scheme, unstructuredObjs...) + fakeDiscoveryClient := &fakeDisco{fakeKubeClient.Discovery(), []*metav1.APIResourceList{ + { + TypeMeta: metav1.TypeMeta{}, + APIResources: scenario.targetAPIResources, + }, + }} + + deployer, err := encryptiondeployer.NewStaticPodDeployer(scenario.targetNamespace, kubeInformers, nil, fakeKubeClient.CoreV1(), fakeSecretClient, fakeOperatorClient) + if err != nil { + t.Fatal(err) + } + + // act + target := NewMigrationController( + deployer, + fakeOperatorClient, + kubeInformers, + fakeSecretClient, + scenario.encryptionSecretSelector, + eventRecorder, + scenario.targetGRs, + fakeDynamicClient, + fakeDiscoveryClient, + ) + err = target.sync() + + // validate + if err == nil && scenario.expectedError != nil { + t.Fatal("expected to get an error from sync() method") + } + if err != nil && scenario.expectedError == nil { + t.Fatal(err) + } + if err != nil && scenario.expectedError != nil && err.Error() != scenario.expectedError.Error() { + t.Fatalf("unexpected error returned = %v, expected = %v", err, scenario.expectedError) + } + if err := encryptiontesting.ValidateActionsVerbs(fakeKubeClient.Actions(), scenario.expectedActions); err != nil { + t.Fatalf("incorrect action(s) detected: %v", err) + } + + if err := encryptiontesting.ValidateActionsVerbs(fakeKubeClient.Actions(), scenario.expectedActions); err != nil { + t.Fatalf("incorrect action(s) detected: %v", err) + } + if scenario.validateFunc != nil { + scenario.validateFunc(t, fakeKubeClient.Actions(), fakeDynamicClient.Actions(), scenario.initialSecrets, scenario.targetGRs, unstructuredObjs) + } + if scenario.validateOperatorClientFunc != nil { + scenario.validateOperatorClientFunc(t, fakeOperatorClient) + } + }) + } +} + +func validateMigratedResources(ts *testing.T, actions []clientgotesting.Action, unstructuredObjs []runtime.Object, targetGRs []schema.GroupResource) { + ts.Helper() + + expectedActionsNoList := len(actions) - len(targetGRs) // subtract "list" requests + if expectedActionsNoList != len(unstructuredObjs) { + ts.Fatalf("incorrect number of resources were encrypted, expected %d, got %d", len(unstructuredObjs), expectedActionsNoList) + } + + // validate LIST requests + { + validatedListRequests := 0 + for _, gr := range targetGRs { + for _, action := range actions { + if action.Matches("list", gr.Resource) { + validatedListRequests++ + break + } + } + } + if validatedListRequests != len(targetGRs) { + ts.Fatalf("incorrect number of LIST request, expedted %d, got %d", len(targetGRs), validatedListRequests) + } + } + + // validate UPDATE requests + for _, action := range actions { + if action.GetVerb() == "update" { + unstructuredObjValidated := false + + updateAction := action.(clientgotesting.UpdateAction) + updatedObj := updateAction.GetObject().(*unstructured.Unstructured) + for _, rawUnstructuredObj := range unstructuredObjs { + expectedUnstructuredObj, ok := rawUnstructuredObj.(*unstructured.Unstructured) + if !ok { + ts.Fatalf("object %T is not *unstructured.Unstructured", expectedUnstructuredObj) + } + if equality.Semantic.DeepEqual(updatedObj, expectedUnstructuredObj) { + unstructuredObjValidated = true + break + } + } + + if !unstructuredObjValidated { + ts.Fatalf("encrypted object with kind = %s, namespace = %s and name = %s wasn't expected to be encrypted", updatedObj.GetKind(), updatedObj.GetNamespace(), updatedObj.GetName()) + } + } + } +} + +func validateSecretsWereAnnotated(ts *testing.T, grs []schema.GroupResource, actions []clientgotesting.Action, expectedSecrets []*corev1.Secret) { + ts.Helper() + + lastSeen := map[string]*corev1.Secret{} + for _, action := range actions { + if !action.Matches("update", "secrets") { + continue + } + updateAction := action.(clientgotesting.UpdateAction) + actualSecret := updateAction.GetObject().(*corev1.Secret) + lastSeen[fmt.Sprintf("%s/%s", actualSecret.Namespace, actualSecret.Name)] = actualSecret + } + + for _, expected := range expectedSecrets { + s, found := lastSeen[fmt.Sprintf("%s/%s", expected.Namespace, expected.Name)] + if !found { + ts.Errorf("missing update on %s/%s", expected.Namespace, expected.Name) + continue + } + if _, ok := s.Annotations[secrets.EncryptionSecretMigratedTimestamp]; !ok { + ts.Errorf("missing %s annotation on %s/%s", secrets.EncryptionSecretMigratedTimestamp, s.Namespace, s.Name) + } + if v, ok := s.Annotations[secrets.EncryptionSecretMigratedResources]; !ok { + ts.Errorf("missing %s annotation on %s/%s", secrets.EncryptionSecretMigratedResources, s.Namespace, s.Name) + } else { + migratedGRs := secrets.MigratedGroupResources{} + if err := json.Unmarshal([]byte(v), &migratedGRs); err != nil { + ts.Errorf("failed to unmarshal %s annotation %q of secret %s/%s: %v", secrets.EncryptionSecretMigratedResources, v, s.Namespace, s.Name, err) + continue + } + migratedGRsSet := map[string]bool{} + for _, gr := range migratedGRs.Resources { + migratedGRsSet[gr.String()] = true + } + for _, gr := range grs { + if _, found := migratedGRsSet[gr.String()]; !found { + ts.Errorf("missing resource %s in %s annotation on %s/%s", gr.String(), secrets.EncryptionSecretMigratedResources, s.Namespace, s.Name) + } + } + } + } +} + +func createConfigMap(name, namespace string) *corev1.ConfigMap { + return &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + } +} + +type fakeDisco struct { + delegate discovery.DiscoveryInterface + serverPreferredRes []*metav1.APIResourceList +} + +func (f *fakeDisco) RESTClient() interface{} { + return f.delegate +} + +func (f *fakeDisco) ServerGroups() (*metav1.APIGroupList, error) { + return f.delegate.ServerGroups() +} + +func (f *fakeDisco) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) { + return f.delegate.ServerResourcesForGroupVersion(groupVersion) +} + +func (f *fakeDisco) ServerGroupsAndResources() ([]*metav1.APIGroup, []*metav1.APIResourceList, error) { + return f.delegate.ServerGroupsAndResources() +} + +func (f *fakeDisco) ServerResources() ([]*metav1.APIResourceList, error) { + return f.delegate.ServerResources() +} + +func (f *fakeDisco) ServerPreferredResources() ([]*metav1.APIResourceList, error) { + return f.serverPreferredRes, nil +} + +func (f *fakeDisco) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) { + return f.delegate.ServerPreferredNamespacedResources() +} + +func (f *fakeDisco) ServerVersion() (*version.Info, error) { + return f.delegate.ServerVersion() +} + +func (f *fakeDisco) OpenAPISchema() (*openapi_v2.Document, error) { + return f.delegate.OpenAPISchema() +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/prune_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/prune_controller.go new file mode 100644 index 0000000000..d54163ed52 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/prune_controller.go @@ -0,0 +1,231 @@ +package controllers + +import ( + "fmt" + "sort" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + utilerrors "k8s.io/apimachinery/pkg/util/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/apimachinery/pkg/util/wait" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/state" + "github.com/openshift/library-go/pkg/operator/encryption/statemachine" + "github.com/openshift/library-go/pkg/operator/events" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +const ( + pruneWorkKey = "key" + keepNumberOfSecrets = 10 +) + +// pruneController prevents an unbounded growth of old encryption keys. +// For a given resource, if there are more than ten keys which have been migrated, +// this controller will delete the oldest migrated keys until there are ten migrated +// keys total. These keys are safe to delete since no data in etcd is encrypted using +// them. Keeping a small number of old keys around is meant to help facilitate +// decryption of old backups (and general precaution). +type pruneController struct { + operatorClient operatorv1helpers.OperatorClient + + queue workqueue.RateLimitingInterface + eventRecorder events.Recorder + + preRunCachesSynced []cache.InformerSynced + + encryptedGRs []schema.GroupResource + + encryptionSecretSelector metav1.ListOptions + + deployer statemachine.Deployer + secretClient corev1client.SecretsGetter +} + +func NewPruneController( + deployer statemachine.Deployer, + operatorClient operatorv1helpers.OperatorClient, + kubeInformersForNamespaces operatorv1helpers.KubeInformersForNamespaces, + secretClient corev1client.SecretsGetter, + encryptionSecretSelector metav1.ListOptions, + eventRecorder events.Recorder, + encryptedGRs []schema.GroupResource, +) *pruneController { + c := &pruneController{ + operatorClient: operatorClient, + + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "EncryptionPruneController"), + eventRecorder: eventRecorder.WithComponentSuffix("encryption-prune-controller"), // TODO unused + + encryptedGRs: encryptedGRs, + + encryptionSecretSelector: encryptionSecretSelector, + deployer: deployer, + secretClient: secretClient, + } + + c.preRunCachesSynced = setUpInformers(deployer, operatorClient, kubeInformersForNamespaces, c.eventHandler()) + + return c +} + +func (c *pruneController) sync() error { + if ready, err := shouldRunEncryptionController(c.operatorClient); err != nil || !ready { + return err // we will get re-kicked when the operator status updates + } + + configError := c.deleteOldMigratedSecrets() + + // update failing condition + cond := operatorv1.OperatorCondition{ + Type: "EncryptionPruneControllerDegraded", + Status: operatorv1.ConditionFalse, + } + if configError != nil { + cond.Status = operatorv1.ConditionTrue + cond.Reason = "Error" + cond.Message = configError.Error() + } + if _, _, updateError := operatorv1helpers.UpdateStatus(c.operatorClient, operatorv1helpers.UpdateConditionFn(cond)); updateError != nil { + return updateError + } + + return configError +} + +func (c *pruneController) deleteOldMigratedSecrets() error { + _, desiredEncryptionConfig, _, isProgressingReason, err := statemachine.GetEncryptionConfigAndState(c.deployer, c.secretClient, c.encryptionSecretSelector, c.encryptedGRs) + if err != nil { + return err + } + if len(isProgressingReason) > 0 { + c.queue.AddAfter(migrationWorkKey, 2*time.Minute) + return nil + } + + allUsedKeys := make([]state.KeyState, 0, len(desiredEncryptionConfig)) + for _, grKeys := range desiredEncryptionConfig { + allUsedKeys = append(allUsedKeys, grKeys.ReadKeys...) + } + + allSecrets, err := c.secretClient.Secrets("openshift-config-managed").List(c.encryptionSecretSelector) + if err != nil { + return err + } + + // sort by keyID + encryptionSecrets := make([]*corev1.Secret, 0, len(allSecrets.Items)) + for _, s := range allSecrets.Items { + encryptionSecrets = append(encryptionSecrets, s.DeepCopy()) // don't use &s because it is constant through-out the loop + } + sort.Slice(encryptionSecrets, func(i, j int) bool { + iKeyID, _ := state.NameToKeyID(encryptionSecrets[i].Name) + jKeyID, _ := state.NameToKeyID(encryptionSecrets[j].Name) + return iKeyID > jKeyID + }) + + var deleteErrs []error + skippedKeys := 0 +NextEncryptionSecret: + for _, s := range encryptionSecrets { + k, err := secrets.ToKeyState(s) + if err == nil { + // ignore invalid keys, check whether secret is used + for _, us := range allUsedKeys { + if state.EqualKeyAndEqualID(&us, &k) { + continue NextEncryptionSecret + } + } + } + + // skip the most recent unused secrets around + if skippedKeys < keepNumberOfSecrets { + skippedKeys++ + continue + } + + // any secret that isn't a read key isn't used. just delete them. + // two phase delete: finalizer, then delete + + // remove our finalizer if it is present + secret := s.DeepCopy() + if finalizers := sets.NewString(secret.Finalizers...); finalizers.Has(secrets.EncryptionSecretFinalizer) { + delete(finalizers, secrets.EncryptionSecretFinalizer) + secret.Finalizers = finalizers.List() + var updateErr error + secret, updateErr = c.secretClient.Secrets("openshift-config-managed").Update(secret) + deleteErrs = append(deleteErrs, updateErr) + if updateErr != nil { + continue + } + } + + // remove the actual secret + if err := c.secretClient.Secrets("openshift-config-managed").Delete(secret.Name, nil); err != nil { + deleteErrs = append(deleteErrs, err) + } else { + klog.V(4).Infof("Successfully pruned secret %s/%s", secret.Namespace, secret.Name) + } + } + return utilerrors.FilterOut(utilerrors.NewAggregate(deleteErrs), errors.IsNotFound) +} + +func (c *pruneController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Infof("Starting EncryptionPruneController") + defer klog.Infof("Shutting down EncryptionPruneController") + if !cache.WaitForCacheSync(stopCh, c.preRunCachesSynced...) { + utilruntime.HandleError(fmt.Errorf("caches did not sync")) + return + } + + // only start one worker + go wait.Until(c.runWorker, time.Second, stopCh) + + <-stopCh +} + +func (c *pruneController) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *pruneController) processNextWorkItem() bool { + dsKey, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(dsKey) + + err := c.sync() + if err == nil { + c.queue.Forget(dsKey) + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with: %v", dsKey, err)) + c.queue.AddRateLimited(dsKey) + + return true +} + +func (c *pruneController) eventHandler() cache.ResourceEventHandler { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.queue.Add(pruneWorkKey) }, + UpdateFunc: func(old, new interface{}) { c.queue.Add(pruneWorkKey) }, + DeleteFunc: func(obj interface{}) { c.queue.Add(pruneWorkKey) }, + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/prune_controller_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/prune_controller_test.go new file mode 100644 index 0000000000..06aee2c2cf --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/prune_controller_test.go @@ -0,0 +1,254 @@ +package controllers + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + "k8s.io/client-go/kubernetes/fake" + clientgotesting "k8s.io/client-go/testing" + + operatorv1 "github.com/openshift/api/operator/v1" + encryptiondeployer "github.com/openshift/library-go/pkg/operator/encryption/deployer" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/state" + encryptiontesting "github.com/openshift/library-go/pkg/operator/encryption/testing" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +func TestPruneController(t *testing.T) { + scenarios := []struct { + name string + initialSecrets []*corev1.Secret + encryptionSecretSelector metav1.ListOptions + targetNamespace string + targetGRs []schema.GroupResource + // expectedActions holds actions to be verified in the form of "verb:resource:namespace" + expectedActions []string + expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration + validateFunc func(ts *testing.T, actions []clientgotesting.Action, initialSecrets []*corev1.Secret) + }{ + { + name: "no-op only 10 keys were migrated", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialSecrets: func() []*corev1.Secret { + ns := "kms" + all := []*corev1.Secret{} + all = append(all, createMigratedEncryptionKeySecretsWithRndKey(t, 10, ns, "secrets")...) + all = append(all, encryptiontesting.CreateEncryptionKeySecretWithRawKey(ns, nil, 11, []byte("cfbbae883984944e48d25590abdfd300"))) + return all + }(), + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "list:secrets:openshift-config-managed"}, + }, + + { + name: "14 keys were migrated, 1 of them is used, 10 are kept, the 3 most recent are pruned", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialSecrets: createMigratedEncryptionKeySecretsWithRndKey(t, 14, "kms", "secrets"), + expectedActions: []string{ + "list:pods:kms", + "get:secrets:kms", + "list:secrets:openshift-config-managed", + "list:secrets:openshift-config-managed", + "update:secrets:openshift-config-managed", + "delete:secrets:openshift-config-managed", + "update:secrets:openshift-config-managed", + "delete:secrets:openshift-config-managed", + "update:secrets:openshift-config-managed", + "delete:secrets:openshift-config-managed", + }, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, initialSecrets []*corev1.Secret) { + validateSecretsWerePruned(ts, actions, initialSecrets[:3]) + }, + }, + + { + name: "no-op the migrated keys don't match the selector", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialSecrets: func() []*corev1.Secret { + return createMigratedEncryptionKeySecretsWithRndKey(t, 15, "not-kms", "secrets") + }(), + encryptionSecretSelector: metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", "encryption.apiserver.operator.openshift.io/component", "kms")}, + expectedActions: []string{ + "list:pods:kms", + "get:secrets:kms", + "list:secrets:openshift-config-managed", + "list:secrets:openshift-config-managed", + }, + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + // setup + fakeOperatorClient := v1helpers.NewFakeStaticPodOperatorClient( + &operatorv1.StaticPodOperatorSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: operatorv1.Managed, + }, + }, + &operatorv1.StaticPodOperatorStatus{ + OperatorStatus: operatorv1.OperatorStatus{ + Conditions: []operatorv1.OperatorCondition{ + { + Type: "EncryptionPruneControllerDegraded", + Status: "False", + }, + }, + }, + NodeStatuses: []operatorv1.NodeStatus{ + {NodeName: "node-1"}, + }, + }, + nil, + nil, + ) + + rawSecrets := []runtime.Object{} + for _, initialSecret := range scenario.initialSecrets { + rawSecrets = append(rawSecrets, initialSecret) + } + + fakePod := encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1") + + writeKeyRaw := []byte("71ea7c91419a68fd1224f88d50316b4e") // NzFlYTdjOTE0MTlhNjhmZDEyMjRmODhkNTAzMTZiNGU= + writeKeyID := uint64(len(scenario.initialSecrets) + 1) + writeKeySecret := encryptiontesting.CreateEncryptionKeySecretWithRawKey(scenario.targetNamespace, nil, writeKeyID, writeKeyRaw) + + initialKeys := []state.KeyState{} + for _, s := range scenario.initialSecrets { + km, err := secrets.ToKeyState(s) + if err != nil { + t.Fatal(err) + } + initialKeys = append(initialKeys, km) + } + + encryptionConfig := func() *corev1.Secret { + additionalReadKeys := state.KeysWithPotentiallyPersistedData(scenario.targetGRs, state.SortRecentFirst(initialKeys)) + var additionaConfigReadKeys []apiserverconfigv1.Key + for _, rk := range additionalReadKeys { + additionaConfigReadKeys = append(additionaConfigReadKeys, apiserverconfigv1.Key{ + Name: rk.Key.Name, + Secret: rk.Key.Secret, + }) + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{{ + Resource: "secrets", + Keys: append([]apiserverconfigv1.Key{ + { + Name: fmt.Sprintf("%d", writeKeyID), + Secret: base64.StdEncoding.EncodeToString(writeKeyRaw), + }, + }, additionaConfigReadKeys...), + }}) + ec.APIVersion = corev1.SchemeGroupVersion.String() + return createEncryptionCfgSecret(t, "kms", "1", ec) + }() + fakeKubeClient := fake.NewSimpleClientset(append(rawSecrets, writeKeySecret, fakePod, encryptionConfig)...) + eventRecorder := events.NewRecorder(fakeKubeClient.CoreV1().Events(scenario.targetNamespace), "test-encryptionKeyController", &corev1.ObjectReference{}) + // we pass "openshift-config-managed" and $targetNamespace ns because the controller creates an informer for secrets in that namespace. + // note that the informer factory is not used in the test - it's only needed to create the controller + kubeInformers := v1helpers.NewKubeInformersForNamespaces(fakeKubeClient, "openshift-config-managed", scenario.targetNamespace) + fakeSecretClient := fakeKubeClient.CoreV1() + + deployer, err := encryptiondeployer.NewStaticPodDeployer(scenario.targetNamespace, kubeInformers, nil, fakeKubeClient.CoreV1(), fakeSecretClient, fakeOperatorClient) + if err != nil { + t.Fatal(err) + } + + target := NewPruneController( + deployer, + fakeOperatorClient, + kubeInformers, + fakeSecretClient, + scenario.encryptionSecretSelector, + eventRecorder, + scenario.targetGRs, + ) + + // act + err = target.sync() + + // validate + if err != nil { + t.Fatal(err) + } + if err := encryptiontesting.ValidateActionsVerbs(fakeKubeClient.Actions(), scenario.expectedActions); err != nil { + t.Fatalf("incorrect action(s) detected: %v", err) + } + if scenario.validateFunc != nil { + scenario.validateFunc(t, fakeKubeClient.Actions(), scenario.initialSecrets) + } + }) + } +} + +func validateSecretsWerePruned(ts *testing.T, actions []clientgotesting.Action, expectedDeletedSecrets []*corev1.Secret) { + ts.Helper() + + deletedSecretsCount := 0 + finalizersRemovedCount := 0 + for _, action := range actions { + if action.GetVerb() == "update" { + updateAction := action.(clientgotesting.UpdateAction) + actualSecret := updateAction.GetObject().(*corev1.Secret) + for _, expectedDeletedSecret := range expectedDeletedSecrets { + if expectedDeletedSecret.Name == actualSecret.GetName() { + expectedDeletedSecretsCpy := expectedDeletedSecret.DeepCopy() + expectedDeletedSecretsCpy.Finalizers = []string{} + if equality.Semantic.DeepEqual(actualSecret, expectedDeletedSecretsCpy) { + finalizersRemovedCount++ + break + } + } + } + } + if action.GetVerb() == "delete" { + deleteAction := action.(clientgotesting.DeleteAction) + for _, expectedDeletedSecret := range expectedDeletedSecrets { + if expectedDeletedSecret.Name == deleteAction.GetName() && expectedDeletedSecret.Namespace == deleteAction.GetNamespace() { + deletedSecretsCount++ + } + } + } + } + if deletedSecretsCount != len(expectedDeletedSecrets) { + ts.Errorf("%d key(s) were deleted but %d were expected to be deleted", deletedSecretsCount, len(expectedDeletedSecrets)) + } + if finalizersRemovedCount != len(expectedDeletedSecrets) { + ts.Errorf("expected to see %d finalizers removed but got %d", len(expectedDeletedSecrets), finalizersRemovedCount) + } +} + +func createMigratedEncryptionKeySecretsWithRndKey(ts *testing.T, count int, namespace, resource string) []*corev1.Secret { + ts.Helper() + rawKey := make([]byte, 32) + if _, err := rand.Read(rawKey); err != nil { + ts.Fatal(err) + } + ret := []*corev1.Secret{} + for i := 1; i <= count; i++ { + s := encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey(namespace, []schema.GroupResource{{Group: "", Resource: resource}}, uint64(i), rawKey, time.Now()) + ret = append(ret, s) + } + return ret +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/state_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/state_controller.go new file mode 100644 index 0000000000..a82f8a003b --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/state_controller.go @@ -0,0 +1,182 @@ +package controllers + +import ( + "fmt" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + "github.com/openshift/library-go/pkg/operator/encryption/statemachine" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/resource/resourceapply" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +const stateWorkKey = "key" + +// stateController is responsible for creating a single secret in +// openshift-config-managed with the name destName. This single secret +// contains the complete EncryptionConfiguration that is consumed by the API +// server that is performing the encryption. Thus this secret represents +// the current state of all resources in encryptedGRs. Every encryption key +// that matches encryptionSecretSelector is included in this final secret. +// This secret is synced into targetNamespace at a static location. This +// indirection allows the cluster to recover from the deletion of targetNamespace. +// See getResourceConfigs for details on how the raw state of all keys +// is converted into a single encryption config. The logic for determining +// the current write key is of special interest. +type stateController struct { + queue workqueue.RateLimitingInterface + eventRecorder events.Recorder + preRunCachesSynced []cache.InformerSynced + + encryptedGRs []schema.GroupResource + component string + encryptionSecretSelector metav1.ListOptions + + operatorClient operatorv1helpers.OperatorClient + secretClient corev1client.SecretsGetter + deployer statemachine.Deployer +} + +func NewStateController( + component string, + deployer statemachine.Deployer, + operatorClient operatorv1helpers.OperatorClient, + kubeInformersForNamespaces operatorv1helpers.KubeInformersForNamespaces, + secretClient corev1client.SecretsGetter, + encryptionSecretSelector metav1.ListOptions, + eventRecorder events.Recorder, + encryptedGRs []schema.GroupResource, +) *stateController { + c := &stateController{ + operatorClient: operatorClient, + + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "EncryptionStateController"), + eventRecorder: eventRecorder.WithComponentSuffix("encryption-state-controller"), + + encryptedGRs: encryptedGRs, + component: component, + + encryptionSecretSelector: encryptionSecretSelector, + secretClient: secretClient, + deployer: deployer, + } + + c.preRunCachesSynced = setUpInformers(deployer, operatorClient, kubeInformersForNamespaces, c.eventHandler()) + + return c +} + +func (c *stateController) sync() error { + if ready, err := shouldRunEncryptionController(c.operatorClient); err != nil || !ready { + return err // we will get re-kicked when the operator status updates + } + + configError := c.generateAndApplyCurrentEncryptionConfigSecret() + + // update failing condition + cond := operatorv1.OperatorCondition{ + Type: "EncryptionStateControllerDegraded", + Status: operatorv1.ConditionFalse, + } + if configError != nil { + cond.Status = operatorv1.ConditionTrue + cond.Reason = "Error" + cond.Message = configError.Error() + } + if _, _, updateError := operatorv1helpers.UpdateStatus(c.operatorClient, operatorv1helpers.UpdateConditionFn(cond)); updateError != nil { + return updateError + } + + return configError +} + +func (c *stateController) generateAndApplyCurrentEncryptionConfigSecret() error { + currentConfig, desiredEncryptionState, secretsFound, transitioningReason, err := statemachine.GetEncryptionConfigAndState(c.deployer, c.secretClient, c.encryptionSecretSelector, c.encryptedGRs) + if err != nil { + return err + } + if len(transitioningReason) > 0 { + c.queue.AddAfter(stateWorkKey, 2*time.Minute) + return nil + } + + if currentConfig == nil && !secretsFound { + // we depend on the key controller to create the first key to bootstrap encryption. + // Later-on either the config exists or there are keys, even in the case of disabled + // encryption via the apiserver config. + return nil + } + + return c.applyEncryptionConfigSecret(encryptionconfig.FromEncryptionState(desiredEncryptionState)) +} + +func (c *stateController) applyEncryptionConfigSecret(encryptionConfig *apiserverconfigv1.EncryptionConfiguration) error { + s, err := encryptionconfig.ToSecret("openshift-config-managed", fmt.Sprintf("%s-%s", encryptionconfig.EncryptionConfSecretName, c.component), encryptionConfig) + if err != nil { + return err + } + + _, _, applyErr := resourceapply.ApplySecret(c.secretClient, c.eventRecorder, s) + return applyErr +} + +func (c *stateController) Run(stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Infof("Starting EncryptionStateController") + defer klog.Infof("Shutting down EncryptionStateController") + if !cache.WaitForCacheSync(stopCh, c.preRunCachesSynced...) { + utilruntime.HandleError(fmt.Errorf("caches did not sync for EncryptionStateController")) + return + } + + // only start one worker + go wait.Until(c.runWorker, time.Second, stopCh) + + <-stopCh +} + +func (c *stateController) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *stateController) processNextWorkItem() bool { + dsKey, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(dsKey) + + err := c.sync() + if err == nil { + c.queue.Forget(dsKey) + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with: %v", dsKey, err)) + c.queue.AddRateLimited(dsKey) + + return true +} + +func (c *stateController) eventHandler() cache.ResourceEventHandler { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.queue.Add(stateWorkKey) }, + UpdateFunc: func(old, new interface{}) { c.queue.Add(stateWorkKey) }, + DeleteFunc: func(obj interface{}) { c.queue.Add(stateWorkKey) }, + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/state_controller_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/state_controller_test.go new file mode 100644 index 0000000000..d79c0affed --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/controllers/state_controller_test.go @@ -0,0 +1,764 @@ +package controllers + +import ( + "encoding/base64" + "errors" + "fmt" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/diff" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + "k8s.io/client-go/kubernetes/fake" + clientgotesting "k8s.io/client-go/testing" + + operatorv1 "github.com/openshift/api/operator/v1" + encryptiondeployer "github.com/openshift/library-go/pkg/operator/encryption/deployer" + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + "github.com/openshift/library-go/pkg/operator/encryption/state" + encryptiontesting "github.com/openshift/library-go/pkg/operator/encryption/testing" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +func TestStateController(t *testing.T) { + scenarios := []struct { + name string + initialResources []runtime.Object + encryptionSecretSelector metav1.ListOptions + targetNamespace string + targetGRs []schema.GroupResource + // expectedActions holds actions to be verified in the form of "verb:resource:namespace" + expectedActions []string + expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration + validateFunc func(ts *testing.T, actions []clientgotesting.Action, destName string, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration) + validateOperatorClientFunc func(ts *testing.T, operatorClient v1helpers.OperatorClient) + expectedError error + }{ + // scenario 1: validates if "encryption-config-kms" secret with EncryptionConfiguration in "openshift-config-managed" namespace + // was not created when no secrets with encryption keys are present in that namespace. + { + name: "no secret with EncryptionConfig is created when there are no secrets with the encryption keys", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + }, + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed"}, + }, + + // scenario 2: validates if "encryption-config-kms" secret with EncryptionConfiguration in "openshift-config-managed" namespace is created, + // it also checks the content and the order of encryption providers, this test expects identity first and aescbc second + { + name: "secret with EncryptionConfig is created without a write key", + targetNamespace: "kms", + encryptionSecretSelector: metav1.ListOptions{LabelSelector: "encryption.apiserver.operator.openshift.io/component=kms"}, + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 1, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed", "create:secrets:openshift-config-managed", "create:events:kms"}, + expectedEncryptionCfg: encryptiontesting.CreateEncryptionCfgNoWriteKey("1", "NjFkZWY5NjRmYjk2N2Y1ZDdjNDRhMmFmOGRhYjY4NjU=", "secrets"), + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, destName string, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration) { + wasSecretValidated := false + for _, action := range actions { + if action.Matches("create", "secrets") { + createAction := action.(clientgotesting.CreateAction) + actualSecret := createAction.GetObject().(*corev1.Secret) + err := validateSecretWithEncryptionConfig(actualSecret, expectedEncryptionCfg, destName) + if err != nil { + ts.Fatalf("failed to verfy the encryption config, due to %v", err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + }, + }, + + // scenario 3 + { + name: "secret with EncryptionConfig is created and it contains a single write key", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 34, []byte("171582a0fcd6c5fdb65cbf5a3e9249d7")), + func() *corev1.Secret { + ec := encryptiontesting.CreateEncryptionCfgNoWriteKey("34", "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", "secrets") + ecs := createEncryptionCfgSecret(t, "kms", "1", ec) + return ecs + }(), + }, + expectedEncryptionCfg: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed", "create:secrets:openshift-config-managed", "create:events:kms"}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, destName string, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration) { + wasSecretValidated := false + for _, action := range actions { + if action.Matches("create", "secrets") { + createAction := action.(clientgotesting.CreateAction) + actualSecret := createAction.GetObject().(*corev1.Secret) + err := validateSecretWithEncryptionConfig(actualSecret, expectedEncryptionCfg, destName) + if err != nil { + ts.Fatalf("failed to verfy the encryption config, due to %v", err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + }, + }, + + // scenario 4 + { + name: "no-op when no key is transitioning", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 34, []byte("171582a0fcd6c5fdb65cbf5a3e9249d7"), time.Now()), + func() *corev1.Secret { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "kms", "1", ec) + return ecs + }(), + func() *corev1.Secret { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "openshift-config-managed", "1", ec) + ecs.Name = "encryption-config-kms" + return ecs + }(), + }, + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed"}, + }, + + // scenario 5 + { + name: "the key with ID=34 is transitioning (observed as a read key) so it is used as a write key in the EncryptionConfig", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 33, []byte("171582a0fcd6c5fdb65cbf5a3e9249d7")), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 34, []byte("dda090c18770163d57d6aaca85f7b3a5")), + func() *corev1.Secret { // encryption config in kms namespace + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "33", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + { + Name: "34", + Secret: "ZGRhMDkwYzE4NzcwMTYzZDU3ZDZhYWNhODVmN2IzYTU=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "kms", "1", ec) + return ecs + }(), + func() *corev1.Secret { // encryption config in openshift-config-managed + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "33", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + { + Name: "34", + Secret: "ZGRhMDkwYzE4NzcwMTYzZDU3ZDZhYWNhODVmN2IzYTU=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "openshift-config-managed", "1", ec) + ecs.Name = "encryption-config-kms" + return ecs + }(), + }, + expectedEncryptionCfg: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "ZGRhMDkwYzE4NzcwMTYzZDU3ZDZhYWNhODVmN2IzYTU=", + }, + { + Name: "33", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed", "update:secrets:openshift-config-managed", "create:events:kms"}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, destName string, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration) { + wasSecretValidated := false + for _, action := range actions { + if action.Matches("update", "secrets") { + updateAction := action.(clientgotesting.UpdateAction) + actualSecret := updateAction.GetObject().(*corev1.Secret) + err := validateSecretWithEncryptionConfig(actualSecret, expectedEncryptionCfg, destName) + if err != nil { + ts.Fatalf("failed to verfy the encryption config, due to %v", err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + }, + }, + + // scenario 6 + { + name: "checks if the order of the keys is preserved and that they read keys are pruned - all migrated", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 31, []byte("a1f1b3e36c477d91ea85af0f32358f70")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 32, []byte("42b07b385a0edee268f1ac41cfc53857")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 33, []byte("b0af82240e10c032fd9bbbedd3b5955a")), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 34, []byte("1c06e8517890c8dc44f627905efc86b8"), time.Now()), + func() *corev1.Secret { // encryption config in kms namespace + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MWMwNmU4NTE3ODkwYzhkYzQ0ZjYyNzkwNWVmYzg2Yjg=", + }, + { + Name: "33", + Secret: "YjBhZjgyMjQwZTEwYzAzMmZkOWJiYmVkZDNiNTk1NWE=", + }, + { + Name: "32", + Secret: "NDJiMDdiMzg1YTBlZGVlMjY4ZjFhYzQxY2ZjNTM4NTc=", + }, + { + Name: "31", + Secret: "YTFmMWIzZTM2YzQ3N2Q5MWVhODVhZjBmMzIzNThmNzA=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "kms", "1", ec) + return ecs + }(), + func() *corev1.Secret { // encryption config in openshift-config-managed namespace + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MWMwNmU4NTE3ODkwYzhkYzQ0ZjYyNzkwNWVmYzg2Yjg=", + }, + { + Name: "33", + Secret: "YjBhZjgyMjQwZTEwYzAzMmZkOWJiYmVkZDNiNTk1NWE=", + }, + { + Name: "32", + Secret: "NDJiMDdiMzg1YTBlZGVlMjY4ZjFhYzQxY2ZjNTM4NTc=", + }, + { + Name: "31", + Secret: "YTFmMWIzZTM2YzQ3N2Q5MWVhODVhZjBmMzIzNThmNzA=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "openshift-config-managed", "1", ec) + ecs.Name = "encryption-config-kms" + return ecs + }(), + }, + expectedEncryptionCfg: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MWMwNmU4NTE3ODkwYzhkYzQ0ZjYyNzkwNWVmYzg2Yjg=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed", "update:secrets:openshift-config-managed", "create:events:kms"}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, destName string, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration) { + wasSecretValidated := false + for _, action := range actions { + if action.Matches("update", "secrets") { + updateAction := action.(clientgotesting.UpdateAction) + actualSecret := updateAction.GetObject().(*corev1.Secret) + err := validateSecretWithEncryptionConfig(actualSecret, expectedEncryptionCfg, destName) + if err != nil { + ts.Fatalf("failed to verfy the encryption config, due to %v", err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + }, + }, + + // scenario 7 + { + name: "checks if the order of the keys is preserved - with a key that is transitioning", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 31, []byte("a1f1b3e36c477d91ea85af0f32358f70")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 32, []byte("42b07b385a0edee268f1ac41cfc53857")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 33, []byte("b0af82240e10c032fd9bbbedd3b5955a")), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 34, []byte("1c06e8517890c8dc44f627905efc86b8")), + func() *corev1.Secret { // encryption config in kms namespace + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "33", + Secret: base64.StdEncoding.EncodeToString([]byte("b0af82240e10c032fd9bbbedd3b5955a")), + }, + { + Name: "34", + Secret: base64.StdEncoding.EncodeToString([]byte("1c06e8517890c8dc44f627905efc86b8")), + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "kms", "1", ec) + return ecs + }(), + func() *corev1.Secret { // encryption config in openshift-config-managed namespace + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "33", + Secret: base64.StdEncoding.EncodeToString([]byte("b0af82240e10c032fd9bbbedd3b5955a")), + }, + { + Name: "34", + Secret: base64.StdEncoding.EncodeToString([]byte("1c06e8517890c8dc44f627905efc86b8")), + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "openshift-config-managed", "1", ec) + ecs.Name = "encryption-config-kms" + return ecs + }(), + }, + expectedEncryptionCfg: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: base64.StdEncoding.EncodeToString([]byte("1c06e8517890c8dc44f627905efc86b8")), + }, + { + Name: "33", + Secret: base64.StdEncoding.EncodeToString([]byte("b0af82240e10c032fd9bbbedd3b5955a")), + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed", "update:secrets:openshift-config-managed", "create:events:kms"}, + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, destName string, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration) { + wasSecretValidated := false + for _, action := range actions { + if action.Matches("update", "secrets") { + updateAction := action.(clientgotesting.UpdateAction) + actualSecret := updateAction.GetObject().(*corev1.Secret) + err := validateSecretWithEncryptionConfig(actualSecret, expectedEncryptionCfg, destName) + if err != nil { + ts.Fatalf("failed to verfy the encryption config, due to %v", err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + }, + }, + + // scenario 8 + // + // BUG: this test simulates deletion of an encryption config in the target ns - the encryption config had a single secret + // as a result a new encryption config is created with a single read key - that effectively means that the encryption was turned off (temporarily) + { + name: "no encryption cfg in the target ns (was deleted)", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 34, []byte("171582a0fcd6c5fdb65cbf5a3e9249d7"), time.Now()), + func() *corev1.Secret { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + ecs := createEncryptionCfgSecret(t, "openshift-config-managed", "1", ec) + ecs.Name = "encryption-config-kms" + return ecs + }(), + }, + expectedEncryptionCfg: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + validateFunc: func(ts *testing.T, actions []clientgotesting.Action, destName string, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration) { + // TODO: fix the temporary identity key on config reconstruction in getDesiredEncryptionState + /* + wasSecretValidated := false + for _, action := range actions { + if action.Matches("update", "secrets") { + updateAction := action.(clientgotesting.UpdateAction) + actualSecret := updateAction.GetObject().(*corev1.Secret) + err := validateSecretWithEncryptionConfig(actualSecret, expectedEncryptionCfg, destName) + if err != nil { + ts.Fatalf("failed to verfy the encryption config, due to %v", err) + } + wasSecretValidated = true + break + } + } + if !wasSecretValidated { + ts.Errorf("the secret wasn't created and validated") + } + */ + }, + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed", "update:secrets:openshift-config-managed", "create:events:kms"}, + }, + + // scenario 9 + // + // verifies if removing a target GR doesn't have effect - we will keep encrypting that GR + { + name: "a user can't stop encrypting config maps", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, 34, []byte("171582a0fcd6c5fdb65cbf5a3e9249d7"), time.Now()), + func() *corev1.Secret { // encryption config in kms namespace + keysRes := []encryptiontesting.EncryptionKeysResourceTuple{ + { + Resource: "configmaps", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + { + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey(keysRes) + ecs := createEncryptionCfgSecret(t, "kms", "1", ec) + return ecs + }(), + func() *corev1.Secret { // encryption config in openshift-config-managed namespace + keysRes := []encryptiontesting.EncryptionKeysResourceTuple{ + { + Resource: "configmaps", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + { + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey(keysRes) + ecs := createEncryptionCfgSecret(t, "openshift-config-managed", "1", ec) + ecs.Name = "encryption-config-kms" + return ecs + }(), + }, + expectedActions: []string{"list:pods:kms", "get:secrets:kms", "list:secrets:openshift-config-managed", "get:secrets:openshift-config-managed"}, + }, + + // scenario 10 + { + name: "degraded a pod with invalid condition", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPodInUnknownPhase("kube-apiserver-1", "kms", "node-1"), + }, + expectedActions: []string{"list:pods:kms"}, + expectedError: errors.New("failed to get converged static pod revision: api server pod kube-apiserver-1 in unknown phase"), + validateOperatorClientFunc: func(ts *testing.T, operatorClient v1helpers.OperatorClient) { + expectedCondition := operatorv1.OperatorCondition{ + Type: "EncryptionStateControllerDegraded", + Status: "True", + Reason: "Error", + Message: "failed to get converged static pod revision: api server pod kube-apiserver-1 in unknown phase", + } + encryptiontesting.ValidateOperatorClientConditions(ts, operatorClient, []operatorv1.OperatorCondition{expectedCondition}) + }, + }, + + // scenario 11 + { + name: "no-op as an invalid secret is not considered", + targetNamespace: "kms", + targetGRs: []schema.GroupResource{ + {Group: "", Resource: "secrets"}, + }, + initialResources: []runtime.Object{ + encryptiontesting.CreateDummyKubeAPIPod("kube-apiserver-1", "kms", "node-1"), + func() *corev1.Secret { // encryption config in kms namespace + ecs := createEncryptionCfgSecret(t, "kms", "1", &apiserverconfigv1.EncryptionConfiguration{}) + ecs.Data[encryptionconfig.EncryptionConfSecretName] = []byte{1, 2, 3} // invalid + return ecs + }(), + }, + expectedActions: []string{"list:pods:kms", "get:secrets:kms"}, + expectedError: fmt.Errorf("invalid encryption config kms/encryption-config-1: yaml: control characters are not allowed"), + validateOperatorClientFunc: func(ts *testing.T, operatorClient v1helpers.OperatorClient) { + expectedCondition := operatorv1.OperatorCondition{ + Type: "EncryptionStateControllerDegraded", + Status: "True", + Reason: "Error", + Message: "invalid encryption config kms/encryption-config-1: yaml: control characters are not allowed", + } + encryptiontesting.ValidateOperatorClientConditions(ts, operatorClient, []operatorv1.OperatorCondition{expectedCondition}) + }, + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + // setup + fakeOperatorClient := v1helpers.NewFakeStaticPodOperatorClient( + &operatorv1.StaticPodOperatorSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: operatorv1.Managed, + }, + }, + &operatorv1.StaticPodOperatorStatus{ + OperatorStatus: operatorv1.OperatorStatus{ + // we need to set up proper conditions before the test starts because + // the controller calls UpdateStatus which calls UpdateOperatorStatus method which is unsupported (fake client) and throws an exception + Conditions: []operatorv1.OperatorCondition{ + { + Type: "EncryptionStateControllerDegraded", + Status: "False", + }, + }, + }, + NodeStatuses: []operatorv1.NodeStatus{ + {NodeName: "node-1"}, + }, + }, + nil, + nil, + ) + + fakeKubeClient := fake.NewSimpleClientset(scenario.initialResources...) + eventRecorder := events.NewRecorder(fakeKubeClient.CoreV1().Events(scenario.targetNamespace), "test-encryptionKeyController", &corev1.ObjectReference{}) + // we pass "openshift-config-managed" and $targetNamespace ns because the controller creates an informer for secrets in that namespace. + // note that the informer factory is not used in the test - it's only needed to create the controller + kubeInformers := v1helpers.NewKubeInformersForNamespaces(fakeKubeClient, "openshift-config-managed", scenario.targetNamespace) + fakeSecretClient := fakeKubeClient.CoreV1() + fakePodClient := fakeKubeClient.CoreV1() + + deployer, err := encryptiondeployer.NewStaticPodDeployer(scenario.targetNamespace, kubeInformers, nil, fakePodClient, fakeSecretClient, fakeOperatorClient) + if err != nil { + t.Fatal(err) + } + target := NewStateController( + scenario.targetNamespace, + deployer, + fakeOperatorClient, + kubeInformers, + fakeSecretClient, + scenario.encryptionSecretSelector, + eventRecorder, + scenario.targetGRs, + ) + + // act + err = target.sync() + + // validate + if err == nil && scenario.expectedError != nil { + t.Fatal("expected to get an error from sync() method") + } + if err != nil && scenario.expectedError == nil { + t.Fatal(err) + } + if err != nil && scenario.expectedError != nil && err.Error() != scenario.expectedError.Error() { + t.Fatalf("unexpected error returned = %v, expected = %v", err, scenario.expectedError) + } + if err := encryptiontesting.ValidateActionsVerbs(fakeKubeClient.Actions(), scenario.expectedActions); err != nil { + t.Fatalf("incorrect action(s) detected: %v", err) + } + if scenario.validateFunc != nil { + scenario.validateFunc(t, fakeKubeClient.Actions(), fmt.Sprintf("%s-%s", encryptionconfig.EncryptionConfSecretName, scenario.targetNamespace), scenario.expectedEncryptionCfg) + } + if scenario.validateOperatorClientFunc != nil { + scenario.validateOperatorClientFunc(t, fakeOperatorClient) + } + }) + } +} + +func validateSecretWithEncryptionConfig(actualSecret *corev1.Secret, expectedEncryptionCfg *apiserverconfigv1.EncryptionConfiguration, expectedSecretName string) error { + actualEncryptionCfg, err := encryptionconfig.FromSecret(actualSecret) + if err != nil { + return fmt.Errorf("failed to verfy the encryption config, due to %v", err) + } + + if !equality.Semantic.DeepEqual(expectedEncryptionCfg, actualEncryptionCfg) { + return fmt.Errorf("%s", diff.ObjectDiff(expectedEncryptionCfg, actualEncryptionCfg)) + } + + // rewrite the payload and compare the rest + expectedSecret := &corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: expectedSecretName, + Namespace: "openshift-config-managed", + Annotations: map[string]string{ + state.KubernetesDescriptionKey: state.KubernetesDescriptionScaryValue, + }, + Finalizers: []string{"encryption.apiserver.operator.openshift.io/deletion-protection"}, + }, + Data: actualSecret.Data, + } + + // those are filled by the server + if len(actualSecret.Kind) == 0 { + actualSecret.Kind = "Secret" + } + if len(actualSecret.APIVersion) == 0 { + actualSecret.APIVersion = corev1.SchemeGroupVersion.String() + } + + if !equality.Semantic.DeepEqual(expectedSecret, actualSecret) { + return fmt.Errorf("%s", diff.ObjectDiff(expectedSecret, actualSecret)) + } + + return nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go new file mode 100644 index 0000000000..2d660ce1d5 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/crypto/keys.go @@ -0,0 +1,27 @@ +package crypto + +import ( + "crypto/rand" + + "github.com/openshift/library-go/pkg/operator/encryption/state" +) + +var ( + ModeToNewKeyFunc = map[state.Mode]func() []byte{ + state.AESCBC: NewAES256Key, + state.SecretBox: NewAES256Key, // secretbox requires a 32 byte key so we can reuse the same function here + state.Identity: NewIdentityKey, + } +) + +func NewAES256Key() []byte { + b := make([]byte, 32) // AES-256 == 32 byte key + if _, err := rand.Read(b); err != nil { + panic(err) // rand should never fail + } + return b +} + +func NewIdentityKey() []byte { + return make([]byte, 16) // the key is not used to perform encryption but must be a valid AES key +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/deployer/staticpod.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/deployer/staticpod.go new file mode 100644 index 0000000000..6f18227820 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/deployer/staticpod.go @@ -0,0 +1,227 @@ +package deployer + +import ( + "fmt" + "strconv" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/informers" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + + operatorv1 "github.com/openshift/api/operator/v1" + + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + "github.com/openshift/library-go/pkg/operator/encryption/statemachine" + "github.com/openshift/library-go/pkg/operator/resourcesynccontroller" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +type StaticPodDeployer struct { + podClient corev1client.PodInterface + secretClient corev1client.SecretInterface + operatorClient operatorv1helpers.StaticPodOperatorClient + + targetNamespaceInformers informers.SharedInformerFactory +} + +var _ statemachine.Deployer = &StaticPodDeployer{} + +// NewStaticPodDeployer create a deployer abstraction meant for the staticpod controllers. It copies +// the encryption-config- from openshift-config-managed namespace to the target namespace +// as encryption-config. From there it is revisioned and deployed to the static pods. The last +// deployed encryption config is read from encryption-config-. +// +// For testing, resourceSyncer might be nil. +func NewStaticPodDeployer( + targetNamespace string, + namespaceInformers operatorv1helpers.KubeInformersForNamespaces, + resourceSyncer resourcesynccontroller.ResourceSyncer, + podClient corev1client.PodsGetter, + secretClient corev1client.SecretsGetter, + operatorClient operatorv1helpers.StaticPodOperatorClient, +) (*StaticPodDeployer, error) { + if resourceSyncer != nil { + if err := resourceSyncer.SyncSecret( + resourcesynccontroller.ResourceLocation{Namespace: targetNamespace, Name: encryptionconfig.EncryptionConfSecretName}, + resourcesynccontroller.ResourceLocation{Namespace: "openshift-config-managed", Name: fmt.Sprintf("%s-%s", encryptionconfig.EncryptionConfSecretName, targetNamespace)}, + ); err != nil { + return nil, err + } + } + + return &StaticPodDeployer{ + podClient: podClient.Pods(targetNamespace), + secretClient: secretClient.Secrets(targetNamespace), + operatorClient: operatorClient, + targetNamespaceInformers: namespaceInformers.InformersFor(targetNamespace), + }, nil +} + +// DeployedEncryptionConfigSecret returns the deployed encryption config and whether all +// instances of the operand have acknowledged it. +func (d *StaticPodDeployer) DeployedEncryptionConfigSecret() (secret *corev1.Secret, converged bool, err error) { + _, status, _, err := d.operatorClient.GetStaticPodOperatorState() + if err != nil { + return nil, false, err + } + if status == nil || len(status.NodeStatuses) == 0 { + return nil, false, nil + } + + revision, err := getAPIServerRevisionOfAllInstances("revision", status.NodeStatuses, d.podClient) + if err != nil { + return nil, false, fmt.Errorf("failed to get converged static pod revision: %v", err) + } + if len(revision) == 0 { + return nil, false, nil + } + + s, err := d.secretClient.Get(encryptionconfig.EncryptionConfSecretName+"-"+revision, metav1.GetOptions{}) + if err != nil { + // if encryption is not enabled at this revision or the secret was deleted, we should not error + if errors.IsNotFound(err) { + return nil, true, nil + } + return nil, false, err + } + return s, true, nil +} + +// AddEventHandler registers a event handler whenever the backing resource change +// that might influence the result of DeployedEncryptionConfigSecret. +func (d *StaticPodDeployer) AddEventHandler(handler cache.ResourceEventHandler) []cache.InformerSynced { + targetPodInformer := d.targetNamespaceInformers.Core().V1().Pods().Informer() + targetPodInformer.AddEventHandler(handler) + + targetSecretsInformer := d.targetNamespaceInformers.Core().V1().Secrets().Informer() + targetSecretsInformer.AddEventHandler(handler) + + d.operatorClient.Informer().AddEventHandler(handler) + + return []cache.InformerSynced{ + targetPodInformer.HasSynced, + targetSecretsInformer.HasSynced, + d.operatorClient.Informer().HasSynced, + } +} + +// getAPIServerRevisionOfAllInstances attempts to find the current revision that +// the API servers are running at. If all API servers have not converged onto a +// a single revision, it returns the empty string and possibly an error. +// Converged can be defined as: +// 1. All running pods are ready and at the same revision +// 2. All master nodes have a running pod +// 3. There are no pending or unknown pods +// 4. All succeeded and failed pods have revisions that are before the running pods +// Once a converged revision has been determined, it can be used to determine +// what encryption config state has been successfully observed by the API servers. +// It assumes that podClient is doing live lookups against the cluster state. +func getAPIServerRevisionOfAllInstances(revisionLabel string, nodes []operatorv1.NodeStatus, podClient corev1client.PodInterface) (string, error) { + // do a live list so we never get confused about what revision we are on + apiServerPods, err := podClient.List(metav1.ListOptions{LabelSelector: "apiserver=true"}) + if err != nil { + return "", err + } + + good, bad, progressing, err := categorizePods(apiServerPods.Items) + if err != nil { + return "", err + } + if progressing { + return "", nil + } + + goodRevisions := revisions(revisionLabel, good) + goodNodes := nodeNames(good) + failingRevisions := revisions(revisionLabel, bad) + + if len(goodRevisions) != 1 { + return "", nil // api servers have not converged onto a single revision + } + revision, _ := goodRevisions.PopAny() + + if failingRevisions.Has(revision) { + return "", fmt.Errorf("api server revision %s has both running and failed pods", revision) + } + + // make sure all expected nodes are there + missingNodes := []string{} + for _, n := range nodes { + if !goodNodes.Has(n.NodeName) { + missingNodes = append(missingNodes, n.NodeName) + } + } + if len(missingNodes) > 0 { + return "", fmt.Errorf("api server pods missing for nodes %v", missingNodes) + } + + revisionNum, err := strconv.Atoi(revision) + if err != nil { + return "", fmt.Errorf("api server has invalid revision: %v", err) + } + + for _, failedRevision := range failingRevisions.List() { // iterate in defined order + failedRevisionNum, err := strconv.Atoi(failedRevision) + if err != nil { + return "", fmt.Errorf("api server has invalid failed revision: %v", err) + } + if failedRevisionNum > revisionNum { // TODO can this dead lock? + return "", fmt.Errorf("api server has failed revision %v which is newer than running revision %v", failedRevisionNum, revisionNum) + } + } + + return revision, nil +} + +func revisions(revisionLabel string, pods []*corev1.Pod) sets.String { + ret := sets.NewString() + for _, p := range pods { + ret.Insert(p.Labels[revisionLabel]) + } + return ret +} + +func nodeNames(pods []*corev1.Pod) sets.String { + ret := sets.NewString() + for _, p := range pods { + ret.Insert(p.Spec.NodeName) + } + return ret +} + +func categorizePods(pods []corev1.Pod) (good []*corev1.Pod, bad []*corev1.Pod, progressing bool, err error) { + for _, apiServerPod := range pods { + switch phase := apiServerPod.Status.Phase; phase { + case corev1.PodRunning: + if !podReady(apiServerPod) { + return nil, nil, true, nil // pods are not fully ready + } + good = append(good, &apiServerPod) + case corev1.PodPending: + return nil, nil, true, nil // pods are not fully ready + case corev1.PodUnknown: + return nil, nil, false, fmt.Errorf("api server pod %s in unknown phase", apiServerPod.Name) + case corev1.PodSucceeded, corev1.PodFailed: + // handle failed pods carefully to make sure things are healthy + // since the API server should never exit, a succeeded pod is considered as failed + bad = append(bad, &apiServerPod) + default: + // error in case new unexpected phases get added + return nil, nil, false, fmt.Errorf("api server pod %s has unexpected phase %v", apiServerPod.Name, phase) + } + } + return good, bad, false, nil +} + +func podReady(pod corev1.Pod) bool { + for _, condition := range pod.Status.Conditions { + if condition.Type == corev1.PodReady && condition.Status == corev1.ConditionTrue { + return true + } + } + return false +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go new file mode 100644 index 0000000000..347ce8caf1 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config.go @@ -0,0 +1,178 @@ +package encryptionconfig + +import ( + "encoding/base64" + "sort" + + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + "k8s.io/klog" + + "github.com/openshift/library-go/pkg/operator/encryption/crypto" + "github.com/openshift/library-go/pkg/operator/encryption/state" +) + +var ( + emptyStaticIdentityKey = base64.StdEncoding.EncodeToString(crypto.NewIdentityKey()) +) + +// FromEncryptionState converts state to config. +func FromEncryptionState(encryptionState map[schema.GroupResource]state.GroupResourceState) *apiserverconfigv1.EncryptionConfiguration { + resourceConfigs := make([]apiserverconfigv1.ResourceConfiguration, 0, len(encryptionState)) + + for gr, grKeys := range encryptionState { + resourceConfigs = append(resourceConfigs, apiserverconfigv1.ResourceConfiguration{ + Resources: []string{gr.String()}, // we are forced to lose data here because this API is broken + Providers: stateToProviders(grKeys), + }) + } + + // make sure our output is stable + sort.Slice(resourceConfigs, func(i, j int) bool { + return resourceConfigs[i].Resources[0] < resourceConfigs[j].Resources[0] // each resource has its own keys + }) + + return &apiserverconfigv1.EncryptionConfiguration{Resources: resourceConfigs} +} + +// ToEncryptionState converts config to state. +// Read keys contain a potential write key. Read keys are sorted, recent first. +// +// It assumes: +// - the first provider provides the write key +// - the structure of the encryptionConfig matches the output generated by FromEncryptionState: +// - one resource per provider +// - one key per provider +// - each resource has a distinct configuration with zero or more key based providers and the identity provider. +// - the last providers might be of type aesgcm. Then it carries the names of identity keys, recent first. +// We never use aesgcm as a real key because it is unsafe. +func ToEncryptionState(encryptionConfig *apiserverconfigv1.EncryptionConfiguration) map[schema.GroupResource]state.GroupResourceState { + if encryptionConfig == nil { + return nil + } + + out := map[schema.GroupResource]state.GroupResourceState{} + for _, resourceConfig := range encryptionConfig.Resources { + // resources should be a single group resource + if len(resourceConfig.Resources) != 1 { + klog.Warningf("skipping invalid encryption config for resource %s", resourceConfig.Resources) + continue // should never happen + } + + grState := state.GroupResourceState{} + + for i, provider := range resourceConfig.Providers { + var ks state.KeyState + + switch { + case provider.AESCBC != nil && len(provider.AESCBC.Keys) == 1: + ks = state.KeyState{ + Key: provider.AESCBC.Keys[0], + Mode: state.AESCBC, + } + + case provider.Secretbox != nil && len(provider.Secretbox.Keys) == 1: + ks = state.KeyState{ + Key: provider.Secretbox.Keys[0], + Mode: state.SecretBox, + } + + case provider.Identity != nil: + // skip fake provider. If this is write-key, wait for first aesgcm provider providing the write key. + continue + + case provider.AESGCM != nil && len(provider.AESGCM.Keys) == 1 && provider.AESGCM.Keys[0].Secret == emptyStaticIdentityKey: + ks = state.KeyState{ + Key: provider.AESGCM.Keys[0], + Mode: state.Identity, + } + + default: + klog.Infof("skipping invalid provider index %d for resource %s", i, resourceConfig.Resources[0]) + continue // should never happen + } + + if i == 0 || (ks.Mode == state.Identity && !grState.HasWriteKey()) { + grState.WriteKey = ks + } + + grState.ReadKeys = append(grState.ReadKeys, ks) // also for write key as they are also read keys + } + + // sort read-keys, recent first + grState.ReadKeys = state.SortRecentFirst(grState.ReadKeys) + + out[schema.ParseGroupResource(resourceConfig.Resources[0])] = grState + } + return out +} + +// stateToProviders maps the write and read secrets to the equivalent read and write keys. +// it primarily handles the conversion of KeyState to the appropriate provider config. +// the identity mode is transformed into a custom aesgcm provider that simply exists to +// curry the associated null key secret through the encryption state machine. +func stateToProviders(desired state.GroupResourceState) []apiserverconfigv1.ProviderConfiguration { + allKeys := desired.ReadKeys + + providers := make([]apiserverconfigv1.ProviderConfiguration, 0, len(allKeys)+1) // one extra for identity + + // Write key comes first. Filter it out in the tail of read keys. + if desired.HasWriteKey() { + allKeys = append([]state.KeyState{desired.WriteKey}, allKeys...) + for i := 1; i < len(allKeys); i++ { + if state.EqualKeyAndEqualID(&allKeys[i], &desired.WriteKey) { + allKeys = append(allKeys[:i], allKeys[i+1:]...) + break + } + } + } else { + // no write key => identity write key + providers = append(providers, apiserverconfigv1.ProviderConfiguration{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }) + } + + aesgcmProviders := []apiserverconfigv1.ProviderConfiguration{} + for i, key := range allKeys { + switch key.Mode { + case state.AESCBC: + providers = append(providers, apiserverconfigv1.ProviderConfiguration{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{key.Key}, + }, + }) + case state.SecretBox: + providers = append(providers, apiserverconfigv1.ProviderConfiguration{ + Secretbox: &apiserverconfigv1.SecretboxConfiguration{ + Keys: []apiserverconfigv1.Key{key.Key}, + }, + }) + case state.Identity: + if i == 0 { + providers = append(providers, apiserverconfigv1.ProviderConfiguration{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }) + } + aesgcmProviders = append(aesgcmProviders, apiserverconfigv1.ProviderConfiguration{ + AESGCM: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{key.Key}, + }, + }) + default: + // this should never happen because our input should always be valid + klog.Infof("skipping key %s as it has invalid mode %s", key.Key.Name, key.Mode) + } + } + + // add fallback identity provider. + if providers[0].Identity == nil { + providers = append(providers, apiserverconfigv1.ProviderConfiguration{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }) + } + + // add fake aesgm providers carrying identity names + providers = append(providers, aesgcmProviders...) + + return providers +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config_test.go new file mode 100644 index 0000000000..75e05249c1 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/config_test.go @@ -0,0 +1,553 @@ +package encryptionconfig + +import ( + "encoding/base64" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/state" + encryptiontesting "github.com/openshift/library-go/pkg/operator/encryption/testing" +) + +func TestToEncryptionState(t *testing.T) { + scenarios := []struct { + name string + input *apiserverconfigv1.EncryptionConfiguration + output map[schema.GroupResource]state.GroupResourceState + }{ + // scenario 1 + { + name: "single write key", + input: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc", + }, + ReadKeys: []state.KeyState{{ + Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc", + }}, + }, + }, + }, + + // scenario 2 + { + name: "multiple keys", + input: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + { + Name: "33", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + {Key: apiserverconfigv1.Key{Name: "33", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + }, + }, + + // scenario 3 + { + name: "single write key multiple resources", + input: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := []encryptiontesting.EncryptionKeysResourceTuple{ + { + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + + { + Resource: "configmaps", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey(keysRes) + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + {Group: "", Resource: "configmaps"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + }, + }, + + // scenario 4 + { + name: "multiple keys and multiple resources", + input: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := []encryptiontesting.EncryptionKeysResourceTuple{ + { + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + { + Name: "33", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + + { + Resource: "configmaps", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + { + Name: "33", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + }, + }, + } + ec := encryptiontesting.CreateEncryptionCfgWithWriteKey(keysRes) + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + {Key: apiserverconfigv1.Key{Name: "33", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + {Group: "", Resource: "configmaps"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + {Key: apiserverconfigv1.Key{Name: "33", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + }, + }, + + // scenario 5 + { + name: "single read key", + input: func() *apiserverconfigv1.EncryptionConfiguration { + ec := encryptiontesting.CreateEncryptionCfgNoWriteKey("34", "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", "secrets") + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + }, + }, + + // scenario 6 + { + name: "single read key multiple resources", + input: func() *apiserverconfigv1.EncryptionConfiguration { + ec := encryptiontesting.CreateEncryptionCfgNoWriteKey("34", "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", "secrets", "configmaps") + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + {Group: "", Resource: "configmaps"}: { + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + }, + }, + + // scenario 7 + { + name: "turn off encryption for single resource", + input: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := encryptiontesting.EncryptionKeysResourceTuple{ + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + { + Name: "35", + Secret: newFakeIdentityEncodedKeyForTest(), + }, + }, + Modes: []string{"aescbc", "aesgcm"}, + } + ec := encryptiontesting.CreateEncryptionCfgNoWriteKeyMultipleReadKeys([]encryptiontesting.EncryptionKeysResourceTuple{keysRes}) + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "35", Secret: newFakeIdentityEncodedKeyForTest()}, Mode: "identity", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "35", Secret: newFakeIdentityEncodedKeyForTest()}, Mode: "identity"}, + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + }, + }, + + // scenario 8 + { + name: "turn off encryption for multiple resources", + input: func() *apiserverconfigv1.EncryptionConfiguration { + keysRes := []encryptiontesting.EncryptionKeysResourceTuple{ + { + Resource: "secrets", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + + // stateToProviders puts "fakeIdentityProvider" as last + { + Name: "35", + Secret: newFakeIdentityEncodedKeyForTest(), + }, + }, + Modes: []string{"aescbc", "aesgcm"}, + }, + + { + Resource: "configmaps", + Keys: []apiserverconfigv1.Key{ + { + Name: "34", + Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc=", + }, + + // stateToProviders puts "fakeIdentityProvider" as last + { + Name: "35", + Secret: newFakeIdentityEncodedKeyForTest(), + }, + }, + Modes: []string{"aescbc", "aesgcm"}, + }, + } + ec := encryptiontesting.CreateEncryptionCfgNoWriteKeyMultipleReadKeys(keysRes) + return ec + }(), + output: map[schema.GroupResource]state.GroupResourceState{ + {Group: "", Resource: "secrets"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "35", Secret: newFakeIdentityEncodedKeyForTest()}, Mode: "identity", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "35", Secret: newFakeIdentityEncodedKeyForTest()}, Mode: "identity"}, + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + + {Group: "", Resource: "configmaps"}: { + WriteKey: state.KeyState{ + Key: apiserverconfigv1.Key{Name: "35", Secret: newFakeIdentityEncodedKeyForTest()}, Mode: "identity", + }, + ReadKeys: []state.KeyState{ + {Key: apiserverconfigv1.Key{Name: "35", Secret: newFakeIdentityEncodedKeyForTest()}, Mode: "identity"}, + {Key: apiserverconfigv1.Key{Name: "34", Secret: "MTcxNTgyYTBmY2Q2YzVmZGI2NWNiZjVhM2U5MjQ5ZDc="}, Mode: "aescbc"}, + }, + }, + }, + }, + + // scenario 9 + // TODO: encryption on after being off + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + actualOutput := ToEncryptionState(scenario.input) + + if len(actualOutput) != len(scenario.output) { + t.Fatalf("expected to get %d GR, got %d", len(scenario.output), len(actualOutput)) + } + for actualGR, actualKeys := range actualOutput { + if _, ok := scenario.output[actualGR]; !ok { + t.Fatalf("unexpected GR %v found", actualGR) + } + expectedKeys, _ := scenario.output[actualGR] + if !cmp.Equal(expectedKeys.WriteKey, actualKeys.WriteKey, cmp.AllowUnexported(state.GroupResourceState{}.WriteKey)) { + t.Fatal(fmt.Errorf("%s", cmp.Diff(expectedKeys.WriteKey, actualKeys.WriteKey, cmp.AllowUnexported(state.GroupResourceState{}.WriteKey)))) + } + if !cmp.Equal(expectedKeys.ReadKeys, actualKeys.ReadKeys, cmp.AllowUnexported(state.GroupResourceState{}.WriteKey)) { + t.Fatal(fmt.Errorf("%s", cmp.Diff(expectedKeys.ReadKeys, actualKeys.ReadKeys, cmp.AllowUnexported(state.GroupResourceState{}.WriteKey)))) + } + } + }) + } +} + +func TestFromEncryptionState(t *testing.T) { + scenarios := []struct { + name string + grs []schema.GroupResource + targetNs string + writeKeyIn *corev1.Secret + readKeysIn []*corev1.Secret + output []apiserverconfigv1.ResourceConfiguration + makeOutput func(writeKey *corev1.Secret, readKeys []*corev1.Secret) []apiserverconfigv1.ResourceConfiguration + }{ + // scenario 1 + { + name: "turn off encryption for single resource", + grs: []schema.GroupResource{{Group: "", Resource: "secrets"}}, + targetNs: "kms", + writeKeyIn: encryptiontesting.CreateEncryptionKeySecretWithRawKeyWithMode("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 3, newFakeIdentityKeyForTest(), "identity"), + readKeysIn: []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 2, []byte("61def964fb967f5d7c44a2af8dab6865")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 1, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + makeOutput: func(writeKey *corev1.Secret, readKeys []*corev1.Secret) []apiserverconfigv1.ResourceConfiguration { + rs := apiserverconfigv1.ResourceConfiguration{} + rs.Resources = []string{"secrets"} + rs.Providers = []apiserverconfigv1.ProviderConfiguration{ + {Identity: &apiserverconfigv1.IdentityConfiguration{}}, + {AESCBC: keyToAESConfiguration(readKeys[0])}, + {AESCBC: keyToAESConfiguration(readKeys[1])}, + {AESGCM: keyToAESConfiguration(writeKey)}, + } + return []apiserverconfigv1.ResourceConfiguration{rs} + }, + }, + + // scenario 2 + { + name: "order of the keys is preserved, the write key comes first, then the read keys finally the identity comes last", + grs: []schema.GroupResource{{Group: "", Resource: "secrets"}}, + targetNs: "kms", + writeKeyIn: encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 3, []byte("16f87d5793a3cb726fb9be7ef8211821")), + readKeysIn: []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 2, []byte("558bf68d6d8ab5dd819eec02901766c1")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 1, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + makeOutput: func(writeKey *corev1.Secret, readKeys []*corev1.Secret) []apiserverconfigv1.ResourceConfiguration { + rs := apiserverconfigv1.ResourceConfiguration{} + rs.Resources = []string{"secrets"} + rs.Providers = []apiserverconfigv1.ProviderConfiguration{ + {AESCBC: keyToAESConfiguration(writeKey)}, + {AESCBC: keyToAESConfiguration(readKeys[0])}, + {AESCBC: keyToAESConfiguration(readKeys[1])}, + {Identity: &apiserverconfigv1.IdentityConfiguration{}}, + } + return []apiserverconfigv1.ResourceConfiguration{rs} + }, + }, + + // scenario 3 + { + name: "the identity comes first up when there are no keys", + grs: []schema.GroupResource{{Group: "", Resource: "secrets"}}, + targetNs: "kms", + makeOutput: func(writeKey *corev1.Secret, readKeys []*corev1.Secret) []apiserverconfigv1.ResourceConfiguration { + rs := apiserverconfigv1.ResourceConfiguration{} + rs.Resources = []string{"secrets"} + rs.Providers = []apiserverconfigv1.ProviderConfiguration{{Identity: &apiserverconfigv1.IdentityConfiguration{}}} + return []apiserverconfigv1.ResourceConfiguration{rs} + }, + }, + + // scenario 4 + { + name: "order of the keys is preserved, the write key comes first, then the read keys finally the identity comes last - multiple resources", + grs: []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, + targetNs: "kms", + writeKeyIn: encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, 3, []byte("16f87d5793a3cb726fb9be7ef8211821")), + readKeysIn: []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, 2, []byte("558bf68d6d8ab5dd819eec02901766c1")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, 1, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + makeOutput: func(writeKey *corev1.Secret, readKeys []*corev1.Secret) []apiserverconfigv1.ResourceConfiguration { + rc := apiserverconfigv1.ResourceConfiguration{} + rc.Resources = []string{"configmaps"} + rc.Providers = []apiserverconfigv1.ProviderConfiguration{ + {AESCBC: keyToAESConfiguration(writeKey)}, + {AESCBC: keyToAESConfiguration(readKeys[0])}, + {AESCBC: keyToAESConfiguration(readKeys[1])}, + {Identity: &apiserverconfigv1.IdentityConfiguration{}}, + } + + rs := apiserverconfigv1.ResourceConfiguration{} + rs.Resources = []string{"secrets"} + rs.Providers = []apiserverconfigv1.ProviderConfiguration{ + {AESCBC: keyToAESConfiguration(writeKey)}, + {AESCBC: keyToAESConfiguration(readKeys[0])}, + {AESCBC: keyToAESConfiguration(readKeys[1])}, + {Identity: &apiserverconfigv1.IdentityConfiguration{}}, + } + + return []apiserverconfigv1.ResourceConfiguration{rc, rs} + }, + }, + + // scenario 5 + { + name: "turn off encryption for multiple resources", + grs: []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, + targetNs: "kms", + writeKeyIn: encryptiontesting.CreateEncryptionKeySecretWithRawKeyWithMode("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, 3, newFakeIdentityKeyForTest(), "identity"), + readKeysIn: []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}, {Group: "", Resource: "configmaps"}}, 2, []byte("61def964fb967f5d7c44a2af8dab6865")), + encryptiontesting.CreateExpiredMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "secrets"}}, 1, []byte("61def964fb967f5d7c44a2af8dab6865")), + }, + makeOutput: func(writeKey *corev1.Secret, readKeys []*corev1.Secret) []apiserverconfigv1.ResourceConfiguration { + rc := apiserverconfigv1.ResourceConfiguration{} + rc.Resources = []string{"configmaps"} + rc.Providers = []apiserverconfigv1.ProviderConfiguration{ + {Identity: &apiserverconfigv1.IdentityConfiguration{}}, + {AESCBC: keyToAESConfiguration(readKeys[0])}, + {AESCBC: keyToAESConfiguration(readKeys[1])}, + {AESGCM: keyToAESConfiguration(writeKey)}, + } + + rs := apiserverconfigv1.ResourceConfiguration{} + rs.Resources = []string{"secrets"} + rs.Providers = []apiserverconfigv1.ProviderConfiguration{ + {Identity: &apiserverconfigv1.IdentityConfiguration{}}, + {AESCBC: keyToAESConfiguration(readKeys[0])}, + {AESCBC: keyToAESConfiguration(readKeys[1])}, + {AESGCM: keyToAESConfiguration(writeKey)}, + } + return []apiserverconfigv1.ResourceConfiguration{rc, rs} + }, + }, + + // scenario 6 + // TODO: encryption on after being off + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + + readKeyStatesIn := make([]state.KeyState, 0, len(scenario.readKeysIn)) + for _, s := range scenario.readKeysIn { + ks, err := secrets.ToKeyState(s) + if err != nil { + t.Fatal(err) + } + readKeyStatesIn = append(readKeyStatesIn, ks) + } + + var writeKeyStateIn state.KeyState + if scenario.writeKeyIn != nil { + var err error + writeKeyStateIn, err = secrets.ToKeyState(scenario.writeKeyIn) + if err != nil { + t.Fatal(err) + } + } + + grState := map[schema.GroupResource]state.GroupResourceState{} + for _, gr := range scenario.grs { + ks := state.GroupResourceState{ + ReadKeys: readKeyStatesIn, + WriteKey: writeKeyStateIn, + } + grState[gr] = ks + } + actualOutput := FromEncryptionState(grState) + expectedOutput := scenario.makeOutput(scenario.writeKeyIn, scenario.readKeysIn) + + if !cmp.Equal(expectedOutput, actualOutput.Resources) { + t.Fatal(fmt.Errorf("%s", cmp.Diff(expectedOutput, actualOutput.Resources))) + } + }) + } +} + +func keyToAESConfiguration(key *corev1.Secret) *apiserverconfigv1.AESConfiguration { + id, ok := state.NameToKeyID(key.Name) + if !ok { + panic(fmt.Sprintf("invalid test secret name %q", key.Name)) + } + return &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{ + { + Name: fmt.Sprintf("%d", id), + Secret: base64.StdEncoding.EncodeToString(key.Data[secrets.EncryptionSecretKeyDataKey]), + }, + }, + } +} + +func newFakeIdentityEncodedKeyForTest() string { + return "AAAAAAAAAAAAAAAAAAAAAA==" +} + +func newFakeIdentityKeyForTest() []byte { + return make([]byte, 16) +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/secret.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/secret.go new file mode 100644 index 0000000000..0a75d5375b --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig/secret.go @@ -0,0 +1,74 @@ +package encryptionconfig + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + + "github.com/openshift/library-go/pkg/operator/encryption/state" +) + +var ( + apiserverScheme = runtime.NewScheme() + apiserverCodecs = serializer.NewCodecFactory(apiserverScheme) +) + +func init() { + utilruntime.Must(apiserverconfigv1.AddToScheme(apiserverScheme)) +} + +// EncryptionConfSecretName is the name of the final encryption config secret that is revisioned per apiserver rollout. +const EncryptionConfSecretName = "encryption-config" + +// EncryptionConfSecretKey is the map data key used to store the raw bytes of the final encryption config. +const EncryptionConfSecretKey = "encryption-config" + +func FromSecret(encryptionConfigSecret *corev1.Secret) (*apiserverconfigv1.EncryptionConfiguration, error) { + data, ok := encryptionConfigSecret.Data[EncryptionConfSecretKey] + if !ok { + return nil, nil + } + + decoder := apiserverCodecs.UniversalDecoder(apiserverconfigv1.SchemeGroupVersion) + encryptionConfigObj, err := runtime.Decode(decoder, data) + if err != nil { + return nil, err + } + + encryptionConfig, ok := encryptionConfigObj.(*apiserverconfigv1.EncryptionConfiguration) + if !ok { + return nil, fmt.Errorf("unexpected wrong type %T", encryptionConfigObj) + } + return encryptionConfig, nil +} + +func ToSecret(ns, name string, encryptionCfg *apiserverconfigv1.EncryptionConfiguration) (*corev1.Secret, error) { + encoder := apiserverCodecs.LegacyCodec(apiserverconfigv1.SchemeGroupVersion) + rawEncryptionCfg, err := runtime.Encode(encoder, encryptionCfg) + if err != nil { + return nil, fmt.Errorf("failed to encode the encryption config: %v", err) + } + + return &corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "Secret", + APIVersion: corev1.SchemeGroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: ns, + Annotations: map[string]string{ + state.KubernetesDescriptionKey: state.KubernetesDescriptionScaryValue, + }, + Finalizers: []string{"encryption.apiserver.operator.openshift.io/deletion-protection"}, + }, + Data: map[string][]byte{ + EncryptionConfSecretName: rawEncryptionCfg, + }, + }, nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/observer/observe_encryption_config.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/observer/observe_encryption_config.go new file mode 100644 index 0000000000..f853c85746 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/observer/observe_encryption_config.go @@ -0,0 +1,75 @@ +package observer + +import ( + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + corev1lister "k8s.io/client-go/listers/core/v1" + + "github.com/openshift/library-go/pkg/operator/configobserver" + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + "github.com/openshift/library-go/pkg/operator/events" +) + +type SecretsListers interface { + SecretLister() corev1lister.SecretLister +} + +// NewEncryptionConfigObserver sets encryption-provider-config flag to /etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config +// in the configuration file if encryption-config in the targetNamespace is found +// +// note: +// the flag is not removed when the encryption-config was accidentally removed +// there is an active reconciliation loop in place that will eventually synchronize the missing resource +func NewEncryptionConfigObserver(targetNamespace string, encryptionConfFilePath string) configobserver.ObserveConfigFunc { + return func(genericListers configobserver.Listers, recorder events.Recorder, existingConfig map[string]interface{}) (map[string]interface{}, []error) { + encryptionConfigPath := []string{"apiServerArguments", "encryption-provider-config"} + listers := genericListers.(SecretsListers) + var errs []error + previouslyObservedConfig := map[string]interface{}{} + + existingEncryptionConfig, _, err := unstructured.NestedStringSlice(existingConfig, encryptionConfigPath...) + if err != nil { + return previouslyObservedConfig, append(errs, err) + } + + if len(existingEncryptionConfig) > 0 { + if err := unstructured.SetNestedStringSlice(previouslyObservedConfig, existingEncryptionConfig, encryptionConfigPath...); err != nil { + errs = append(errs, err) + } + } + + previousEncryptionConfigFound := len(existingEncryptionConfig) > 0 + observedConfig := map[string]interface{}{} + + encryptionConfigSecret, err := listers.SecretLister().Secrets(targetNamespace).Get(encryptionconfig.EncryptionConfSecretName) + if errors.IsNotFound(err) { + // warn only if the encryption-provider-config flag was set before + if previousEncryptionConfigFound { + recorder.Warningf("ObserveEncryptionConfigNotFound", "encryption config secret %s/%s not found after encryption has been enabled", targetNamespace, encryptionconfig.EncryptionConfSecretName) + } + // encryption secret is optional so it doesn't prevent apiserver from running + // there is an active reconciliation loop in place that will eventually synchronize the missing resource + return previouslyObservedConfig, errs // do not append the not found error + } + if err != nil { + recorder.Warningf("ObserveEncryptionConfigGetErr", "failed to get encryption config secret %s/%s: %v", targetNamespace, encryptionconfig.EncryptionConfSecretName, err) + return previouslyObservedConfig, append(errs, err) + } + if len(encryptionConfigSecret.Data[encryptionconfig.EncryptionConfSecretKey]) == 0 { + recorder.Warningf("ObserveEncryptionConfigNoData", "encryption config secret %s/%s missing data", targetNamespace, encryptionconfig.EncryptionConfSecretName) + return previouslyObservedConfig, errs + } + + if err := unstructured.SetNestedStringSlice(observedConfig, []string{encryptionConfFilePath}, encryptionConfigPath...); err != nil { + recorder.Warningf("ObserveEncryptionConfigFailedSet", "failed setting encryption config: %v", err) + return previouslyObservedConfig, append(errs, err) + } + + if !equality.Semantic.DeepEqual(existingEncryptionConfig, []string{encryptionConfFilePath}) { + recorder.Eventf("ObserveEncryptionConfigChanged", "encryption config file changed from %s to %s", existingEncryptionConfig, encryptionConfFilePath) + } + + return observedConfig, errs + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/observer/observe_encryption_config_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/observer/observe_encryption_config_test.go new file mode 100644 index 0000000000..146504d9a6 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/observer/observe_encryption_config_test.go @@ -0,0 +1,178 @@ +package observer + +import ( + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + corelistersv1 "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" + + "github.com/openshift/library-go/pkg/operator/configobserver" + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + encryptiontesting "github.com/openshift/library-go/pkg/operator/encryption/testing" + "github.com/openshift/library-go/pkg/operator/events" +) + +type secretsListers struct { + configobserver.Listers + + secretLister_ corelistersv1.SecretLister +} + +func (l secretsListers) SecretLister() corelistersv1.SecretLister { + return l.secretLister_ +} + +func TestEncryptionConfigObserver(t *testing.T) { + scenarios := []struct { + name string + input map[string]interface{} + initialResources []runtime.Object + + expectedOutput map[string]interface{} + expectedEvents []*corev1.Event + }{ + // scenario 1 + { + name: "a secret with encryption config exits thus encryption-provider-config flag is set", + initialResources: func() []runtime.Object { + ret := []runtime.Object{} + ec := encryptiontesting.CreateEncryptionCfgNoWriteKey("1", "NjFkZWY5NjRmYjk2N2Y1ZDdjNDRhMmFmOGRhYjY4NjU=", "secrets") + ecs, err := encryptionconfig.ToSecret("kms", "encryption-config", ec) + if err != nil { + t.Fatal(err) + } + ret = append(ret, ecs) + return ret + }(), + expectedOutput: func() map[string]interface{} { + ret := map[string]interface{}{} + ret["apiServerArguments"] = map[string]interface{}{ + "encryption-provider-config": []interface{}{"/etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config"}, + } + return ret + }(), + expectedEvents: []*corev1.Event{ + {Reason: "ObserveEncryptionConfigChanged", Message: "encryption config file changed from [] to /etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config"}, + }, + }, + + // scenario 2 + { + name: "no secret with encryption config exits thus no encryption-provider-config flag is set", + expectedOutput: map[string]interface{}{}, + expectedEvents: []*corev1.Event{}, // we expect no events + }, + + // scenario 3 + { + name: "encryption-provider-config flag was set in the past but the secret with encryption config is missing", + input: func() map[string]interface{} { + ret := map[string]interface{}{} + ret["apiServerArguments"] = map[string]interface{}{ + "encryption-provider-config": []interface{}{"/etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config"}, + } + return ret + }(), + expectedOutput: func() map[string]interface{} { + ret := map[string]interface{}{} + ret["apiServerArguments"] = map[string]interface{}{ + "encryption-provider-config": []interface{}{"/etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config"}, + } + return ret + }(), + expectedEvents: []*corev1.Event{ + {Reason: "ObserveEncryptionConfigNotFound", Message: "encryption config secret kms/encryption-config not found after encryption has been enabled"}, + }, + }, + + // scenario 4 + { + name: "warn about encryption-provider-config value change", + initialResources: func() []runtime.Object { + ret := []runtime.Object{} + ec := encryptiontesting.CreateEncryptionCfgNoWriteKey("1", "NjFkZWY5NjRmYjk2N2Y1ZDdjNDRhMmFmOGRhYjY4NjU=", "secrets") + ecs, err := encryptionconfig.ToSecret("kms", "encryption-config", ec) + if err != nil { + t.Fatal(err) + } + ret = append(ret, ecs) + return ret + }(), + input: func() map[string]interface{} { + ret := map[string]interface{}{} + ret["apiServerArguments"] = map[string]interface{}{ + "encryption-provider-config": []interface{}{"some_path"}, + } + return ret + }(), + expectedOutput: func() map[string]interface{} { + ret := map[string]interface{}{} + ret["apiServerArguments"] = map[string]interface{}{ + "encryption-provider-config": []interface{}{"/etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config"}, + } + return ret + }(), + expectedEvents: []*corev1.Event{ + {Reason: "ObserveEncryptionConfigChanged", Message: "encryption config file changed from [some_path] to /etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config"}, + }, + }, + } + + for _, scenario := range scenarios { + t.Run(scenario.name, func(t *testing.T) { + listers := secretsListers{} + { + indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{}) + for _, obj := range scenario.initialResources { + err := indexer.Add(obj) + if err != nil { + t.Fatal(err) + } + } + listers.secretLister_ = corelistersv1.NewSecretLister(indexer) + } + eventRec := events.NewInMemoryRecorder("encryption-config-observer") + + target := NewEncryptionConfigObserver("kms", "/etc/kubernetes/static-pod-resources/secrets/encryption-config/encryption-config") + result, err := target(listers, eventRec, scenario.input) + if err != nil { + t.Fatal(err) + } + + if !cmp.Equal(result, scenario.expectedOutput) { + t.Fatal(fmt.Errorf("%s", cmp.Diff(result, scenario.expectedOutput))) + } + + // validate events + { + recordedEvents := eventRec.Events() + if len(scenario.expectedEvents) != len(recordedEvents) { + t.Fatalf("expected to observe %d events but got %d", len(scenario.expectedEvents), len(recordedEvents)) + } + + for _, recordedEvent := range recordedEvents { + expectedEvent := recordedEvent.DeepCopy() + recordedEventFound := false + + for _, expectedEventShort := range scenario.expectedEvents { + expectedEvent.Message = expectedEventShort.Message + expectedEvent.Reason = expectedEventShort.Reason + if cmp.Equal(expectedEvent, recordedEvent) { + recordedEventFound = true + break + } + } + + if !recordedEventFound { + t.Fatalf("expected event with reason = %q and message %q wasn't found\n recorded events = %v", expectedEvent.Reason, expectedEvent.Message, recordedEvents) + } + } + } + }) + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go new file mode 100644 index 0000000000..0c8249d0c6 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets.go @@ -0,0 +1,124 @@ +package secrets + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "strconv" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + + "github.com/openshift/library-go/pkg/operator/encryption/state" +) + +// ToKeyState converts a key secret to a key state. +func ToKeyState(s *corev1.Secret) (state.KeyState, error) { + data := s.Data[EncryptionSecretKeyDataKey] + + keyID, validKeyID := state.NameToKeyID(s.Name) + if !validKeyID { + return state.KeyState{}, fmt.Errorf("secret %s/%s has an invalid name", s.Namespace, s.Name) + } + + key := state.KeyState{ + Key: apiserverconfigv1.Key{ + // we use keyID as the name to limit the length of the field as it is used as a prefix for every value in etcd + Name: strconv.FormatUint(keyID, 10), + Secret: base64.StdEncoding.EncodeToString(data), + }, + Backed: true, + } + + if v, ok := s.Annotations[EncryptionSecretMigratedTimestamp]; ok { + ts, err := time.Parse(time.RFC3339, v) + if err != nil { + return state.KeyState{}, fmt.Errorf("secret %s/%s has invalid %s annotation: %v", s.Namespace, s.Name, EncryptionSecretMigratedTimestamp, err) + } + key.Migrated.Timestamp = ts + } + + if v, ok := s.Annotations[EncryptionSecretMigratedResources]; ok && len(v) > 0 { + migrated := &MigratedGroupResources{} + if err := json.Unmarshal([]byte(v), migrated); err != nil { + return state.KeyState{}, fmt.Errorf("secret %s/%s has invalid %s annotation: %v", s.Namespace, s.Name, EncryptionSecretMigratedResources, err) + } + key.Migrated.Resources = migrated.Resources + } + + if v, ok := s.Annotations[encryptionSecretInternalReason]; ok && len(v) > 0 { + key.InternalReason = v + } + if v, ok := s.Annotations[encryptionSecretExternalReason]; ok && len(v) > 0 { + key.ExternalReason = v + } + + keyMode := state.Mode(s.Annotations[encryptionSecretMode]) + switch keyMode { + case state.AESCBC, state.SecretBox, state.Identity: + key.Mode = keyMode + default: + return state.KeyState{}, fmt.Errorf("secret %s/%s has invalid mode: %s", s.Namespace, s.Name, keyMode) + } + if keyMode != state.Identity && len(data) == 0 { + return state.KeyState{}, fmt.Errorf("secret %s/%s of mode %q must have non-empty key", s.Namespace, s.Name, keyMode) + } + + return key, nil +} + +// ToKeyState converts a key state to a key secret. +func FromKeyState(component string, ks state.KeyState) (*corev1.Secret, error) { + bs, err := base64.StdEncoding.DecodeString(ks.Key.Secret) + if err != nil { + return nil, fmt.Errorf("failed to decode key string") + } + + s := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("encryption-key-%s-%s", component, ks.Key.Name), + Namespace: "openshift-config-managed", + Labels: map[string]string{ + EncryptionKeySecretsLabel: component, + }, + Annotations: map[string]string{ + state.KubernetesDescriptionKey: state.KubernetesDescriptionScaryValue, + + encryptionSecretMode: string(ks.Mode), + encryptionSecretInternalReason: ks.InternalReason, + encryptionSecretExternalReason: ks.ExternalReason, + }, + Finalizers: []string{EncryptionSecretFinalizer}, + }, + Data: map[string][]byte{ + EncryptionSecretKeyDataKey: bs, + }, + } + + if !ks.Migrated.Timestamp.IsZero() { + s.Annotations[EncryptionSecretMigratedTimestamp] = ks.Migrated.Timestamp.Format(time.RFC3339) + } + if len(ks.Migrated.Resources) > 0 { + migrated := MigratedGroupResources{Resources: ks.Migrated.Resources} + bs, err := json.Marshal(migrated) + if err != nil { + return nil, err + } + s.Annotations[EncryptionSecretMigratedResources] = string(bs) + } + + return s, nil +} + +// HasResource returns whether the given group resource is contained in the migrated group resource list. +func (m *MigratedGroupResources) HasResource(resource schema.GroupResource) bool { + for _, gr := range m.Resources { + if gr == resource { + return true + } + } + return false +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets_test.go new file mode 100644 index 0000000000..9eb97cd83a --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/secrets_test.go @@ -0,0 +1,96 @@ +package secrets + +import ( + "encoding/base64" + "reflect" + "testing" + "time" + + "k8s.io/apimachinery/pkg/runtime/schema" + v1 "k8s.io/apiserver/pkg/apis/config/v1" + "k8s.io/utils/diff" + + "github.com/openshift/library-go/pkg/operator/encryption/state" +) + +func TestRoundtrip(t *testing.T) { + now, _ := time.Parse(time.RFC3339, time.Now().Format(time.RFC3339)) + + tests := []struct { + name string + component string + ks state.KeyState + }{ + { + name: "full aescbc", + component: "kms", + ks: state.KeyState{ + Key: v1.Key{ + Name: "54", + Secret: base64.StdEncoding.EncodeToString([]byte("abcdef")), + }, + Backed: true, // this will be set by ToKeyState() + Mode: "aescbc", + Migrated: state.MigrationState{ + Timestamp: now, + Resources: []schema.GroupResource{ + {Resource: "secrets"}, + {Resource: "configmaps"}, + {Group: "networking.openshift.io", Resource: "routes"}, + }, + }, + InternalReason: "internal", + ExternalReason: "external", + }, + }, + { + name: "sparse aescbc", + component: "kms", + ks: state.KeyState{ + Key: v1.Key{ + Name: "54", + Secret: base64.StdEncoding.EncodeToString([]byte("abcdef")), + }, + Backed: true, // this will be set by ToKeyState() + Mode: "aescbc", + }, + }, + { + name: "identity", + component: "kms", + ks: state.KeyState{ + Key: v1.Key{ + Name: "54", + Secret: "", + }, + Backed: true, // this will be set by ToKeyState() + Mode: "identity", + Migrated: state.MigrationState{ + Timestamp: now, + Resources: []schema.GroupResource{ + {Resource: "secrets"}, + {Resource: "configmaps"}, + {Group: "networking.openshift.io", Resource: "routes"}, + }, + }, + InternalReason: "internal", + ExternalReason: "external", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s, err := FromKeyState(tt.component, tt.ks) + if err != nil { + t.Fatalf("unexpected FromKeyState() error: %v", err) + } + got, err := ToKeyState(s) + if err != nil { + t.Fatalf("unexpected ToKeyState() error: %v", err) + } + if !reflect.DeepEqual(got, tt.ks) { + t.Errorf("roundtrip error:\n%s", diff.ObjectDiff(tt.ks, got)) + } + }) + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go new file mode 100644 index 0000000000..7161e4a124 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/secrets/types.go @@ -0,0 +1,59 @@ +package secrets + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" +) + +const ( + // This label is used to find secrets that build up the final encryption config. The names of the + // secrets are in format - (the uint is the keyID). + // For example, openshift-kube-apiserver-encryption-3. Note that other than the -3 postfix, the name of + // the secret is irrelevant since the label is used to find the secrets. Of course the key minting + // controller cares about the entire name since it needs to know when it has already created a secret for a given + // keyID meaning it cannot just use a random prefix. As such the name must include the data that is contained + // within the label. Thus the format used is -encryption-. This keeps everything distinct + // and fully deterministic. The keys are ordered by keyID where a smaller ID means an earlier key. + // This means that the latest secret (the one with the largest keyID) is the current desired write key. + EncryptionKeySecretsLabel = "encryption.apiserver.operator.openshift.io/component" + + // These annotations are used to mark the current observed state of a secret. + + // The time (in RFC3339 format) at which the migrated state observation occurred. The key minting + // controller parses this field to determine if enough time has passed and a new key should be created. + EncryptionSecretMigratedTimestamp = "encryption.apiserver.operator.openshift.io/migrated-timestamp" + // The list of resources that were migrated when encryptionSecretMigratedTimestamp was set. + // See the MigratedGroupResources struct below to understand the JSON encoding used. + EncryptionSecretMigratedResources = "encryption.apiserver.operator.openshift.io/migrated-resources" + + // encryptionSecretMode is the annotation that determines how the provider associated with a given key is + // configured. For example, a key could be used with AES-CBC or Secretbox. This allows for algorithm + // agility. When the default mode used by the key minting controller changes, it will force the creation + // of a new key under the new mode even if encryptionSecretMigrationInterval has not been reached. + encryptionSecretMode = "encryption.apiserver.operator.openshift.io/mode" + + // encryptionSecretInternalReason is the annotation that denotes why a particular key + // was created based on "internal" reasons (i.e. key minting controller decided a new + // key was needed for some reason X). It is tracked solely for the purposes of debugging. + encryptionSecretInternalReason = "encryption.apiserver.operator.openshift.io/internal-reason" + + // encryptionSecretExternalReason is the annotation that denotes why a particular key was created based on + // "external" reasons (i.e. force key rotation for some reason Y). It allows the key minting controller to + // determine if a new key should be created even if encryptionSecretMigrationInterval has not been reached. + encryptionSecretExternalReason = "encryption.apiserver.operator.openshift.io/external-reason" + + // In the data field of the secret API object, this (map) key is used to hold the actual encryption key + // (i.e. for AES-CBC mode the value associated with this map key is 32 bytes of random noise). + EncryptionSecretKeyDataKey = "encryption.apiserver.operator.openshift.io-key" + + // encryptionSecretFinalizer is a finalizer attached to all secrets generated + // by the encryption controllers. Its sole purpose is to prevent the accidental + // deletion of secrets by enforcing a two phase delete. + EncryptionSecretFinalizer = "encryption.apiserver.operator.openshift.io/deletion-protection" +) + +// MigratedGroupResources is the data structured stored in the +// encryption.apiserver.operator.openshift.io/migrated-resources +// of a key secret. +type MigratedGroupResources struct { + Resources []schema.GroupResource `json:"resources"` +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go new file mode 100644 index 0000000000..420f97092c --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/helpers.go @@ -0,0 +1,80 @@ +package state + +import ( + "fmt" + "sort" + "strconv" + "strings" + + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// MigratedFor returns whether all given resources are marked as migrated in the given key. +// It returns missing GRs and a reason if that's not the case. +func MigratedFor(grs []schema.GroupResource, km KeyState) (ok bool, missing []schema.GroupResource, reason string) { + var missingStrings []string + for _, gr := range grs { + found := false + for _, mgr := range km.Migrated.Resources { + if mgr == gr { + found = true + break + } + } + if !found { + missing = append(missing, gr) + missingStrings = append(missingStrings, gr.String()) + } + } + + if len(missing) > 0 { + return false, missing, fmt.Sprintf("key ID %s misses resource %s among migrated resources", km.Key.Name, strings.Join(missingStrings, ",")) + } + + return true, nil, "" +} + +// KeysWithPotentiallyPersistedData returns the minimal, recent secrets which have migrated all given GRs. +func KeysWithPotentiallyPersistedData(grs []schema.GroupResource, recentFirstSortedKeys []KeyState) []KeyState { + for i, k := range recentFirstSortedKeys { + if allMigrated, missing, _ := MigratedFor(grs, k); allMigrated { + return recentFirstSortedKeys[:i+1] + } else { + // continue with keys we haven't found a migration key for yet + grs = missing + } + } + return recentFirstSortedKeys +} + +func SortRecentFirst(unsorted []KeyState) []KeyState { + ret := make([]KeyState, len(unsorted)) + copy(ret, unsorted) + sort.Slice(ret, func(i, j int) bool { + // it is fine to ignore the validKeyID bool here because we filtered out invalid secrets in the loop above + iKeyID, _ := NameToKeyID(ret[i].Key.Name) + jKeyID, _ := NameToKeyID(ret[j].Key.Name) + return iKeyID > jKeyID + }) + return ret +} + +func NameToKeyID(name string) (uint64, bool) { + lastIdx := strings.LastIndex(name, "-") + idString := name + if lastIdx >= 0 { + idString = name[lastIdx+1:] // this can never overflow since str[-1+1:] is + } + id, err := strconv.ParseUint(idString, 10, 0) + return id, err == nil +} + +func EqualKeyAndEqualID(s1, s2 *KeyState) bool { + if s1.Mode != s2.Mode || s1.Key.Secret != s2.Key.Secret { + return false + } + + id1, valid1 := NameToKeyID(s1.Key.Name) + id2, valid2 := NameToKeyID(s2.Key.Name) + return valid1 && valid2 && id1 == id2 +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go new file mode 100644 index 0000000000..9a7174e43c --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/state/types.go @@ -0,0 +1,69 @@ +package state + +import ( + "time" + + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" +) + +// These annotations try to scare anyone away from editing the encryption secrets. It is trivial for +// an external actor to break the invariants of the state machine and render the cluster unrecoverable. +const ( + KubernetesDescriptionKey = "kubernetes.io/description" + KubernetesDescriptionScaryValue = `WARNING: DO NOT EDIT. +Altering of the encryption secrets will render you cluster inaccessible. +Catastrophic data loss can occur from the most minor changes.` +) + +// GroupResourceState represents, for a single group resource, the write and read keys in a +// format that can be directly translated to and from the on disk EncryptionConfiguration object. +type GroupResourceState struct { + // the write key of the group resource. + WriteKey KeyState + // all read keys of the group resource. Potentially includes the write key. + ReadKeys []KeyState +} + +func (k GroupResourceState) HasWriteKey() bool { + return len(k.WriteKey.Key.Name) > 0 && len(k.WriteKey.Key.Secret) > 0 +} + +type KeyState struct { + Key apiserverconfigv1.Key + Mode Mode + + // described whether it is backed by a secret. + Backed bool + Migrated MigrationState + // some controller logic caused this secret to be created by the key controller. + InternalReason string + // the user via unsupportConfigOverrides.encryption.reason triggered this key. + ExternalReason string +} + +type MigrationState struct { + // the timestamp fo the last migration + Timestamp time.Time + // the resources that were migrated at some point in time to this key. + Resources []schema.GroupResource +} + +// Mode is the value associated with the encryptionSecretMode annotation +type Mode string + +// The current set of modes that are supported along with the default Mode that is used. +// These values are encoded into the secret and thus must not be changed. +// Strings are used over iota because they are easier for a human to understand. +const ( + AESCBC Mode = "aescbc" // available from the first release, see defaultMode below + SecretBox Mode = "secretbox" // available from the first release, see defaultMode below + Identity Mode = "identity" // available from the first release, see defaultMode below + + // Changing this value requires caution to not break downgrades. + // Specifically, if some new Mode is released in version X, that new Mode cannot + // be used as the defaultMode until version X+1. Thus on a downgrade the operator + // from version X will still be able to honor the observed encryption state + // (and it will do a key rotation to force the use of the old defaultMode). + DefaultMode = Identity // we default to encryption being disabled for now +) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/statemachine/transition.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/statemachine/transition.go new file mode 100644 index 0000000000..78ae605ea2 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/statemachine/transition.go @@ -0,0 +1,224 @@ +package statemachine + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/klog" + + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/state" +) + +// Deployer abstracts the deployment machanism like the static pod controllers. +type Deployer interface { + // DeployedEncryptionConfigSecret returns the deployed encryption config and whether all + // instances of the operand have acknowledged it. + DeployedEncryptionConfigSecret() (secret *corev1.Secret, converged bool, err error) + + // AddEventHandler registers a event handler whenever the backing resource change + // that might influence the result of DeployedEncryptionConfigSecret. + AddEventHandler(handler cache.ResourceEventHandler) []cache.InformerSynced +} + +func GetEncryptionConfigAndState( + deployer Deployer, + secretClient corev1client.SecretsGetter, + encryptionSecretSelector metav1.ListOptions, + encryptedGRs []schema.GroupResource, +) (current *apiserverconfigv1.EncryptionConfiguration, desired map[schema.GroupResource]state.GroupResourceState, secretsFound bool, transitioningReason string, err error) { + // get current config + encryptionConfigSecret, converged, err := deployer.DeployedEncryptionConfigSecret() + if err != nil { + return nil, nil, false, "", err + } + if !converged { + return nil, nil, false, "APIServerRevisionNotConverged", nil + } + var encryptionConfig *apiserverconfigv1.EncryptionConfiguration + if encryptionConfigSecret != nil { + encryptionConfig, err = encryptionconfig.FromSecret(encryptionConfigSecret) + if err != nil { + return nil, nil, false, "", fmt.Errorf("invalid encryption config %s/%s: %v", encryptionConfigSecret.Namespace, encryptionConfigSecret.Name, err) + } + } + + // compute desired config + encryptionSecretList, err := secretClient.Secrets("openshift-config-managed").List(encryptionSecretSelector) + if err != nil { + return nil, nil, false, "", err + } + var encryptionSecrets []*corev1.Secret + for i := range encryptionSecretList.Items { + encryptionSecrets = append(encryptionSecrets, &encryptionSecretList.Items[i]) + } + desiredEncryptionState := getDesiredEncryptionState(encryptionConfig, encryptionSecrets, encryptedGRs) + + return encryptionConfig, desiredEncryptionState, len(encryptionSecrets) > 0, "", nil +} + +// getDesiredEncryptionState returns the desired state of encryption for all resources. +// To do this it compares the current state against the available secrets and to-be-encrypted resources. +// oldEncryptionConfig can be nil if there is no config yet. +// If there are no secrets, the identity is set for all resources as write key. +// It is assumed that encryptionSecrets are all valid. +// +// The basic rules are: +// +// 1. don't do anything if there are key secrets. +// 2. every GR must have all the read-keys (existing as secrets) since last complete migration. +// 3. if (2) is the case, the write-key must be the most recent key. +// 4. if (2) and (3) are the case, all non-write keys should be removed. +func getDesiredEncryptionState(oldEncryptionConfig *apiserverconfigv1.EncryptionConfiguration, encryptionSecrets []*corev1.Secret, toBeEncryptedGRs []schema.GroupResource) map[schema.GroupResource]state.GroupResourceState { + backedKeys := make([]state.KeyState, 0, len(encryptionSecrets)) + for _, s := range encryptionSecrets { + km, err := secrets.ToKeyState(s) + if err != nil { + klog.Warningf("skipping invalid secret: %v", err) + continue + } + backedKeys = append(backedKeys, km) + } + backedKeys = state.SortRecentFirst(backedKeys) + + // + // STEP 0: start with old encryption config, and alter it towards the desired state in the following STEPs. + // + desiredEncryptionState := encryptionconfig.ToEncryptionState(oldEncryptionConfig) + if desiredEncryptionState == nil { + desiredEncryptionState = make(map[schema.GroupResource]state.GroupResourceState, len(toBeEncryptedGRs)) + } + + // add new resources without keys. These resources will trigger STEP 2. + oldEncryptedGRs := make([]schema.GroupResource, 0, len(desiredEncryptionState)) + for _, gr := range toBeEncryptedGRs { + if _, ok := desiredEncryptionState[gr]; !ok { + desiredEncryptionState[gr] = state.GroupResourceState{} + } else { + oldEncryptedGRs = append(oldEncryptedGRs, gr) + } + } + + // + // STEP 1: without secrets, wait for the key controller to create one + // + // the code after this point assumes at least one secret + if len(backedKeys) == 0 { + klog.V(4).Infof("no encryption secrets found") + return desiredEncryptionState + } + + // enrich KeyState with values from secrets + for gr, grState := range desiredEncryptionState { + for i, rk := range grState.ReadKeys { + for _, k := range backedKeys { + if state.EqualKeyAndEqualID(&rk, &k) { + grState.ReadKeys[i] = k + break + } + } + } + if grState.HasWriteKey() { + for _, s := range backedKeys { + if state.EqualKeyAndEqualID(&grState.WriteKey, &s) { + grState.WriteKey = s + break + } + } + } + desiredEncryptionState[gr] = grState + } + + // + // STEP 2: verify to have all necessary read-keys. If not, add them, deploy and wait for stability. + // + // Note: we never drop keys here. Dropping only happens in STEP 4. + // Note: only keysWithPotentiallyPersistedData are considered. There might be more which are not pruned yet by the pruning controller. + // + // TODO: allow removing resources (e.g. on downgrades) and transition back to identity. + allReadSecretsAsExpected := true + currentlyEncryptedGRs := oldEncryptedGRs + if oldEncryptionConfig == nil { + // if the config is not there, we assume it was deleted. Assume worst case when finding + // potentially persisted data keys. + currentlyEncryptedGRs = toBeEncryptedGRs + } + expectedReadSecrets := state.KeysWithPotentiallyPersistedData(currentlyEncryptedGRs, backedKeys) + for gr, grState := range desiredEncryptionState { + changed := false + for _, expected := range expectedReadSecrets { + found := false + for _, rk := range grState.ReadKeys { + if state.EqualKeyAndEqualID(&rk, &expected) { + found = true + break + } + } + if !found { + // Just adding raw key without trusting any metadata on it + grState.ReadKeys = append(grState.ReadKeys, expected) + changed = true + allReadSecretsAsExpected = false + klog.V(4).Infof("encrypted resource %s misses read key %s", gr, expected.Key.Name) + } + } + if changed { + grState.ReadKeys = state.SortRecentFirst(grState.ReadKeys) + desiredEncryptionState[gr] = grState + } + + // potential write-key must be backed. Otherwise stop here in STEP 2 and let key controller create a new key. + if !grState.ReadKeys[0].Backed { + allReadSecretsAsExpected = false + } + } + if !allReadSecretsAsExpected { + klog.V(4).Infof("not all read secrets in sync") + return desiredEncryptionState + } + + // + // STEP 3: with consistent read-keys, verify first read-key is write-key. If not, set write-key and wait for stability. + // + writeKey := backedKeys[0] + allWriteSecretsAsExpected := true + for gr, grState := range desiredEncryptionState { + if !grState.HasWriteKey() || !state.EqualKeyAndEqualID(&grState.WriteKey, &writeKey) { + allWriteSecretsAsExpected = false + klog.V(4).Infof("encrypted resource %s does not have write key %s", gr, writeKey.Key.Name) + break + } + } + if !allWriteSecretsAsExpected { + klog.V(4).Infof("not all write secrets in sync") + for gr := range desiredEncryptionState { + grState := desiredEncryptionState[gr] + grState.WriteKey = writeKey + desiredEncryptionState[gr] = grState + } + return desiredEncryptionState + } + + // + // STEP 4: with consistent read-keys and write-keys, remove every read-key other than the write-key. + // + // Note: because read-keys are consistent, currentlyEncryptedGRs equals toBeEncryptedGRs + allMigrated, _, reason := state.MigratedFor(currentlyEncryptedGRs, writeKey) + if !allMigrated { + klog.V(4).Infof(reason) + return desiredEncryptionState + } + for gr := range desiredEncryptionState { + grState := desiredEncryptionState[gr] + grState.ReadKeys = []state.KeyState{writeKey} + desiredEncryptionState[gr] = grState + } + klog.V(4).Infof("write key %s set as sole write key", writeKey.Key.Name) + return desiredEncryptionState +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/statemachine/transition_test.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/statemachine/transition_test.go new file mode 100644 index 0000000000..07b5bcd7f5 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/statemachine/transition_test.go @@ -0,0 +1,949 @@ +package statemachine + +import ( + "encoding/base64" + "reflect" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + "k8s.io/utils/diff" + + "github.com/openshift/library-go/pkg/operator/encryption/encryptionconfig" + "github.com/openshift/library-go/pkg/operator/encryption/state" + encryptiontesting "github.com/openshift/library-go/pkg/operator/encryption/testing" +) + +func TestGetDesiredEncryptionState(t *testing.T) { + type args struct { + oldEncryptionConfig *apiserverconfigv1.EncryptionConfiguration + targetNamespace string + encryptionSecrets []*corev1.Secret + toBeEncryptedGRs []schema.GroupResource + } + type ValidateState func(ts *testing.T, args *args, state map[schema.GroupResource]state.GroupResourceState) + + equalsConfig := func(expected *apiserverconfigv1.EncryptionConfiguration) func(ts *testing.T, args *args, state map[schema.GroupResource]state.GroupResourceState) { + return func(ts *testing.T, _ *args, state map[schema.GroupResource]state.GroupResourceState) { + if expected == nil && state != nil { + ts.Errorf("expected nil state, got: %#v", state) + return + } + if expected != nil && state == nil { + ts.Errorf("expected non-nil state corresponding to config %#v", expected) + return + } + if expected == nil && state == nil { + return + } + expected := expected.DeepCopy() + expected.TypeMeta = metav1.TypeMeta{} + encryptionConfig := encryptionconfig.FromEncryptionState(state) + if !reflect.DeepEqual(expected, encryptionConfig) { + ts.Errorf("unexpected encryption config (A: expected, B: got):\n%s", diff.ObjectDiff(expected, encryptionConfig)) + } + } + } + + outputMatchingInputConfig := func(ts *testing.T, args *args, state map[schema.GroupResource]state.GroupResourceState) { + equalsConfig(args.oldEncryptionConfig)(ts, args, state) + } + + tests := []struct { + name string + args args + validate ValidateState + }{ + { + "first run: no config, no secrets => nothing done, state with identities for each resource", + args{ + nil, + "kms", + nil, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }, + }), + }, + { + "config exists without write keys, no secrets => nothing done, config unchanged", + args{ + encryptiontesting.CreateEncryptionCfgNoWriteKey("1", "NzFlYTdjOTE0MTlhNjhmZDEyMjRmODhkNTAzMTZiNGU=", "configmaps", "secrets"), + "kms", + nil, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + outputMatchingInputConfig, + }, + { + "config exists with write keys, no secrets => nothing done, config unchanged", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}, + }, + "kms", + nil, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}}), + }, + { + "config exists with only one resource => 2nd resource is added", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}, + }, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("71ea7c91419a68fd1224f88d50316b4e")), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }}, + }, + }, + }), + }, + { + "config exists with two resources => 2nd resource stays", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}, + }, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("71ea7c91419a68fd1224f88d50316b4e")), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }, + }), + }, + { + "no config, secrets exist => first config is created", + args{ + nil, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("71ea7c91419a68fd1224f88d50316b4e")), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("71ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }}, + }, + }}), + }, + { + "no config, multiple secrets exists, some migrated => config is recreated, with identity as write key", + args{ + nil, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 5, []byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}}, 4, []byte("447907494bßc4897b876c8476bf807bc"), time.Now()), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, 3, []byte("3cbfbe7d76876e076b076c659cd895ff"), time.Now()), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}}, 2, []byte("2b234b23cb23c4b2cb24cb24bcbffbca")), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, 1, []byte("11ea7c91419a68fd1224f88d50316b4a"), time.Now()), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "4", + Secret: base64.StdEncoding.EncodeToString([]byte("447907494bßc4897b876c8476bf807bc")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "3", + Secret: base64.StdEncoding.EncodeToString([]byte("3cbfbe7d76876e076b076c659cd895ff")), + }}, + }, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "4", + Secret: base64.StdEncoding.EncodeToString([]byte("447907494bßc4897b876c8476bf807bc")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "3", + Secret: base64.StdEncoding.EncodeToString([]byte("3cbfbe7d76876e076b076c659cd895ff")), + }}, + }, + }}, + }, + }}), + }, + { + "config exists, write key secret is missing => no-op", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "4", + Secret: base64.StdEncoding.EncodeToString([]byte("447907494bßc4897b876c8476bf807bc")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "3", + Secret: base64.StdEncoding.EncodeToString([]byte("3cbfbe7d76876e076b076c659cd895ff")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "4", + Secret: base64.StdEncoding.EncodeToString([]byte("447907494bßc4897b876c8476bf807bc")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "3", + Secret: base64.StdEncoding.EncodeToString([]byte("3cbfbe7d76876e076b076c659cd895ff")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }}, + "kms", + []*corev1.Secret{ + // missing: encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 5, []byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}}, 4, []byte("447907494bßc4897b876c8476bf807bc"), time.Now()), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, 3, []byte("3cbfbe7d76876e076b076c659cd895ff"), time.Now()), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}}, 2, []byte("2b234b23cb23c4b2cb24cb24bcbffbca")), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, 1, []byte("11ea7c91419a68fd1224f88d50316b4a"), time.Now()), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + // 4 is becoming new write key, not 5! + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "4", + Secret: base64.StdEncoding.EncodeToString([]byte("447907494bßc4897b876c8476bf807bc")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "3", + Secret: base64.StdEncoding.EncodeToString([]byte("3cbfbe7d76876e076b076c659cd895ff")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "4", + Secret: base64.StdEncoding.EncodeToString([]byte("447907494bßc4897b876c8476bf807bc")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "3", + Secret: base64.StdEncoding.EncodeToString([]byte("3cbfbe7d76876e076b076c659cd895ff")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }}), + }, + { + "config exists without identity => identity is appended", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }}, + }, + }}, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 5, []byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "5", + Secret: base64.StdEncoding.EncodeToString([]byte("55b5bcbc85cb857c7c07c56c54983cbcd")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }, + }), + }, + { + "config exists, new key secret => new key added as read key", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}, + }, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("11ea7c91419a68fd1224f88d50316b4e")), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 2, []byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }, + }), + }, + { + "config exists, read keys are consistent => new write key is set", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}, + }, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("11ea7c91419a68fd1224f88d50316b4e")), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 2, []byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }, + }), + }, + { + "config exists, read+write keys are consistent, not migrated => nothing changes", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}, + }, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("11ea7c91419a68fd1224f88d50316b4e")), + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 2, []byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }, + }), + }, + { + "config exists, read+write keys are consistent, migrated => old read-keys are pruned from config", + args{ + &apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{{ + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "1", + Secret: base64.StdEncoding.EncodeToString([]byte("11ea7c91419a68fd1224f88d50316b4e")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }}, + }, + "kms", + []*corev1.Secret{ + encryptiontesting.CreateEncryptionKeySecretWithRawKey("kms", nil, 1, []byte("11ea7c91419a68fd1224f88d50316b4e")), + encryptiontesting.CreateMigratedEncryptionKeySecretWithRawKey("kms", []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, 2, []byte("2bc2bdbc2bec2ebce7b27ce792639723"), time.Now()), + }, + []schema.GroupResource{{Group: "", Resource: "configmaps"}, {Group: "", Resource: "secrets"}}, + }, + equalsConfig(&apiserverconfigv1.EncryptionConfiguration{ + Resources: []apiserverconfigv1.ResourceConfiguration{ + { + Resources: []string{"configmaps"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + { + Resources: []string{"secrets"}, + Providers: []apiserverconfigv1.ProviderConfiguration{{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{{ + Name: "2", + Secret: base64.StdEncoding.EncodeToString([]byte("2bc2bdbc2bec2ebce7b27ce792639723")), + }}, + }, + }, { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }}, + }, + }, + }), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := getDesiredEncryptionState(tt.args.oldEncryptionConfig, tt.args.encryptionSecrets, tt.args.toBeEncryptedGRs) + if tt.validate != nil { + tt.validate(t, &tt.args, got) + } + }) + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/encryption/testing/helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/encryption/testing/helpers.go new file mode 100644 index 0000000000..886c123e29 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/encryption/testing/helpers.go @@ -0,0 +1,280 @@ +package testing + +import ( + "encoding/json" + "errors" + "fmt" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" + clientgotesting "k8s.io/client-go/testing" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/encryption/state" + "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +const ( + encryptionSecretKeyDataForTest = "encryption.apiserver.operator.openshift.io-key" + encryptionSecretMigratedTimestampForTest = "encryption.apiserver.operator.openshift.io/migrated-timestamp" + encryptionSecretMigratedResourcesForTest = "encryption.apiserver.operator.openshift.io/migrated-resources" +) + +func CreateEncryptionKeySecretNoData(targetNS string, grs []schema.GroupResource, keyID uint64) *corev1.Secret { + return CreateEncryptionKeySecretNoDataWithMode(targetNS, grs, keyID, "aescbc") +} + +func CreateEncryptionKeySecretNoDataWithMode(targetNS string, grs []schema.GroupResource, keyID uint64, mode string) *corev1.Secret { + s := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("encryption-key-%s-%d", targetNS, keyID), + Namespace: "openshift-config-managed", + Annotations: map[string]string{ + state.KubernetesDescriptionKey: state.KubernetesDescriptionScaryValue, + + "encryption.apiserver.operator.openshift.io/mode": mode, + "encryption.apiserver.operator.openshift.io/internal-reason": "no-secrets", + "encryption.apiserver.operator.openshift.io/external-reason": "", + }, + Labels: map[string]string{ + "encryption.apiserver.operator.openshift.io/component": targetNS, + }, + Finalizers: []string{"encryption.apiserver.operator.openshift.io/deletion-protection"}, + }, + Data: map[string][]byte{}, + } + + if len(grs) > 0 { + migratedResourceBytes, err := json.Marshal(secrets.MigratedGroupResources{Resources: grs}) + if err != nil { + panic(err) + } + s.Annotations[encryptionSecretMigratedResourcesForTest] = string(migratedResourceBytes) + } + + return s +} + +func CreateEncryptionKeySecretWithRawKey(targetNS string, grs []schema.GroupResource, keyID uint64, rawKey []byte) *corev1.Secret { + return CreateEncryptionKeySecretWithRawKeyWithMode(targetNS, grs, keyID, rawKey, "aescbc") +} + +func CreateEncryptionKeySecretWithRawKeyWithMode(targetNS string, grs []schema.GroupResource, keyID uint64, rawKey []byte, mode string) *corev1.Secret { + secret := CreateEncryptionKeySecretNoDataWithMode(targetNS, grs, keyID, mode) + secret.Data[encryptionSecretKeyDataForTest] = rawKey + return secret +} + +func CreateEncryptionKeySecretWithKeyFromExistingSecret(targetNS string, grs []schema.GroupResource, keyID uint64, existingSecret *corev1.Secret) *corev1.Secret { + secret := CreateEncryptionKeySecretNoData(targetNS, grs, keyID) + if rawKey, exist := existingSecret.Data[encryptionSecretKeyDataForTest]; exist { + secret.Data[encryptionSecretKeyDataForTest] = rawKey + } + return secret +} + +func CreateMigratedEncryptionKeySecretWithRawKey(targetNS string, grs []schema.GroupResource, keyID uint64, rawKey []byte, ts time.Time) *corev1.Secret { + secret := CreateEncryptionKeySecretWithRawKey(targetNS, grs, keyID, rawKey) + secret.Annotations[encryptionSecretMigratedTimestampForTest] = ts.Format(time.RFC3339) + return secret +} + +func CreateExpiredMigratedEncryptionKeySecretWithRawKey(targetNS string, grs []schema.GroupResource, keyID uint64, rawKey []byte) *corev1.Secret { + return CreateMigratedEncryptionKeySecretWithRawKey(targetNS, grs, keyID, rawKey, time.Now().Add(-(time.Hour*24*7 + time.Hour))) +} + +func CreateDummyKubeAPIPod(name, namespace string, nodeName string) *corev1.Pod { + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + Labels: map[string]string{ + "apiserver": "true", + "revision": "1", + }, + }, + Spec: corev1.PodSpec{ + NodeName: nodeName, + }, + Status: corev1.PodStatus{ + Phase: corev1.PodRunning, + Conditions: []corev1.PodCondition{ + { + Type: corev1.PodReady, + Status: corev1.ConditionTrue, + }, + }, + }, + } +} + +func CreateDummyKubeAPIPodInUnknownPhase(name, namespace string, nodeName string) *corev1.Pod { + p := CreateDummyKubeAPIPod(name, namespace, nodeName) + p.Status.Phase = corev1.PodUnknown + return p +} + +func ValidateActionsVerbs(actualActions []clientgotesting.Action, expectedActions []string) error { + if len(actualActions) != len(expectedActions) { + return fmt.Errorf("expected to get %d actions but got %d, expected=%v, got=%v", len(expectedActions), len(actualActions), expectedActions, actionStrings(actualActions)) + } + for i, a := range actualActions { + if got, expected := actionString(a), expectedActions[i]; got != expected { + return fmt.Errorf("at %d got %s, expected %s", i, got, expected) + } + } + return nil +} + +func actionString(a clientgotesting.Action) string { + return a.GetVerb() + ":" + a.GetResource().Resource + ":" + a.GetNamespace() +} + +func actionStrings(actions []clientgotesting.Action) []string { + res := make([]string, 0, len(actions)) + for _, a := range actions { + res = append(res, actionString(a)) + } + return res +} + +func CreateEncryptionCfgNoWriteKey(keyID string, keyBase64 string, resources ...string) *apiserverconfigv1.EncryptionConfiguration { + keysResources := []EncryptionKeysResourceTuple{} + for _, resource := range resources { + keysResources = append(keysResources, EncryptionKeysResourceTuple{ + Resource: resource, + Keys: []apiserverconfigv1.Key{ + {Name: keyID, Secret: keyBase64}, + }, + }) + + } + return CreateEncryptionCfgNoWriteKeyMultipleReadKeys(keysResources) +} + +func CreateEncryptionCfgNoWriteKeyMultipleReadKeys(keysResources []EncryptionKeysResourceTuple) *apiserverconfigv1.EncryptionConfiguration { + ec := &apiserverconfigv1.EncryptionConfiguration{ + TypeMeta: metav1.TypeMeta{ + Kind: "EncryptionConfiguration", + APIVersion: "apiserver.config.k8s.io/v1", + }, + Resources: []apiserverconfigv1.ResourceConfiguration{}, + } + + for _, keysResource := range keysResources { + rc := apiserverconfigv1.ResourceConfiguration{ + Resources: []string{keysResource.Resource}, + Providers: []apiserverconfigv1.ProviderConfiguration{ + { + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }, + }, + } + for i, key := range keysResource.Keys { + desiredMode := "" + if len(keysResource.Modes) == len(keysResource.Keys) { + desiredMode = keysResource.Modes[i] + } + switch desiredMode { + case "aesgcm": + rc.Providers = append(rc.Providers, apiserverconfigv1.ProviderConfiguration{ + AESGCM: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{key}, + }, + }) + default: + rc.Providers = append(rc.Providers, apiserverconfigv1.ProviderConfiguration{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{key}, + }, + }) + } + } + ec.Resources = append(ec.Resources, rc) + } + + return ec +} + +func CreateEncryptionCfgWithWriteKey(keysResources []EncryptionKeysResourceTuple) *apiserverconfigv1.EncryptionConfiguration { + configurations := []apiserverconfigv1.ResourceConfiguration{} + for _, keysResource := range keysResources { + // TODO allow secretbox -> not sure if EncryptionKeysResourceTuple makes sense + providers := []apiserverconfigv1.ProviderConfiguration{} + for _, key := range keysResource.Keys { + providers = append(providers, apiserverconfigv1.ProviderConfiguration{ + AESCBC: &apiserverconfigv1.AESConfiguration{ + Keys: []apiserverconfigv1.Key{key}, + }, + }) + } + providers = append(providers, apiserverconfigv1.ProviderConfiguration{ + Identity: &apiserverconfigv1.IdentityConfiguration{}, + }) + + configurations = append(configurations, apiserverconfigv1.ResourceConfiguration{ + Resources: []string{keysResource.Resource}, + Providers: providers, + }) + } + + return &apiserverconfigv1.EncryptionConfiguration{ + TypeMeta: metav1.TypeMeta{ + Kind: "EncryptionConfiguration", + APIVersion: "apiserver.config.k8s.io/v1", + }, + Resources: configurations, + } +} + +type EncryptionKeysResourceTuple struct { + Resource string + Keys []apiserverconfigv1.Key + // an ordered list of an encryption modes thatch matches the keys + // for example mode[0] matches keys[0] + Modes []string +} + +func ValidateOperatorClientConditions(ts *testing.T, operatorClient v1helpers.OperatorClient, expectedConditions []operatorv1.OperatorCondition) { + ts.Helper() + _, status, _, err := operatorClient.GetOperatorState() + if err != nil { + ts.Fatal(err) + } + + if len(status.Conditions) != len(expectedConditions) { + ts.Fatalf("expected to get %d conditions from operator client but got %d:\n\nexpected=%v\n\ngot=%v", len(expectedConditions), len(status.Conditions), expectedConditions, status.Conditions) + } + + for _, actualCondition := range status.Conditions { + actualConditionValidated := false + for _, expectedCondition := range expectedConditions { + expectedCondition.LastTransitionTime = actualCondition.LastTransitionTime + if equality.Semantic.DeepEqual(expectedCondition, actualCondition) { + actualConditionValidated = true + break + } + } + if !actualConditionValidated { + ts.Fatalf("unexpected condition found %#v", actualCondition) + } + + } +} + +func ValidateEncryptionKey(secret *corev1.Secret) error { + rawKey, exist := secret.Data[encryptionSecretKeyDataForTest] + if !exist { + return errors.New("the secret doesn't contain an encryption key") + } + if len(rawKey) != 32 { + return fmt.Errorf("incorrect length of the encryption key, expected 32, got %d bytes", len(rawKey)) + } + return nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/core.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/core.go index b4f11db966..da1a1cfa35 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/core.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/core.go @@ -234,23 +234,7 @@ func ApplySecret(client coreclientv1.SecretsGetter, recorder events.Recorder, re existingCopy.Data = required.Data if klog.V(4) { - safeRequired := required.DeepCopy() - safeExisting := existing.DeepCopy() - - for s := range safeExisting.Data { - safeExisting.Data[s] = []byte("OLD") - } - for s := range safeRequired.Data { - if _, preexisting := existing.Data[s]; !preexisting { - safeRequired.Data[s] = []byte("NEW") - } else if !equality.Semantic.DeepEqual(existing.Data[s], safeRequired.Data[s]) { - safeRequired.Data[s] = []byte("MODIFIED") - } else { - safeRequired.Data[s] = []byte("OLD") - } - } - - klog.Infof("Secret %q changes: %v", required.Namespace+"/"+required.Name, JSONPatch(safeExisting, safeRequired)) + klog.Infof("Secret %s/%s changes: %v", required.Namespace, required.Name, JSONPatchSecret(existing, required)) } actual, err := client.Secrets(required.Namespace).Update(existingCopy) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/json_patch_helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/json_patch_helpers.go index c5077f48e8..c053be7aba 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/json_patch_helpers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/json_patch_helpers.go @@ -4,6 +4,9 @@ import ( "fmt" patch "github.com/evanphx/json-patch" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" ) @@ -31,3 +34,25 @@ func JSONPatch(original, modified runtime.Object) string { } return string(patchBytes) } + +// JSONPatchSecret generates a JSON patch between original and modified secrets, hiding its data, +// and return the JSON as a string. In case of error, the returned string will contain the error messages. +func JSONPatchSecret(original, modified *corev1.Secret) string { + safeModified := modified.DeepCopy() + safeOriginal := original.DeepCopy() + + for s := range safeOriginal.Data { + safeOriginal.Data[s] = []byte("OLD") + } + for s := range safeModified.Data { + if _, preoriginal := original.Data[s]; !preoriginal { + safeModified.Data[s] = []byte("NEW") + } else if !equality.Semantic.DeepEqual(original.Data[s], safeModified.Data[s]) { + safeModified.Data[s] = []byte("MODIFIED") + } else { + safeModified.Data[s] = []byte("OLD") + } + } + + return JSONPatch(safeOriginal, safeModified) +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go index e581a4418e..f2d8b5dc0a 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/certsyncpod/certsync_controller.go @@ -79,6 +79,7 @@ func getSecretDir(targetDir, secretName string) string { func (c *CertSyncController) sync() error { errors := []error{} + klog.Infof("Syncing configmaps: %v", c.configMaps) for _, cm := range c.configMaps { configMap, err := c.configMapLister.ConfigMaps(c.namespace).Get(cm.Name) switch { @@ -101,11 +102,14 @@ func (c *CertSyncController) sync() error { // remove missing content if err := os.RemoveAll(getConfigMapDir(c.destinationDir, cm.Name)); err != nil { + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed removing file for configmap: %s/%s: %v", configMap.Namespace, configMap.Name, err) errors = append(errors, err) } + c.eventRecorder.Eventf("CertificateRemoved", "Removed file for configmap: %s/%s", configMap.Namespace, configMap.Name) continue case err != nil: + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed getting configmap: %s/%s: %v", configMap.Namespace, configMap.Name, err) errors = append(errors, err) continue } @@ -138,6 +142,7 @@ func (c *CertSyncController) sync() error { configMap, err = c.configmapGetter.Get(configMap.Name, metav1.GetOptions{}) if err != nil { // Even if the error is not exists we will act on it when caches catch up + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed getting configmap: %s/%s: %v", configMap.Namespace, configMap.Name, err) errors = append(errors, err) continue } @@ -150,6 +155,7 @@ func (c *CertSyncController) sync() error { klog.Infof("Creating directory %q ...", contentDir) if err := os.MkdirAll(contentDir, 0755); err != nil && !os.IsExist(err) { + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed creating directory for configmap: %s/%s: %v", configMap.Namespace, configMap.Name, err) errors = append(errors, err) continue } @@ -162,12 +168,15 @@ func (c *CertSyncController) sync() error { klog.Infof("Writing configmap manifest %q ...", fullFilename) if err := ioutil.WriteFile(fullFilename, []byte(content), 0644); err != nil { + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed writing file for configmap: %s/%s: %v", configMap.Namespace, configMap.Name, err) errors = append(errors, err) continue } } + c.eventRecorder.Eventf("CertificateUpdated", "Wrote updated configmap: %s/%s", configMap.Namespace, configMap.Name) } + klog.Infof("Syncing secrets: %v", c.secrets) for _, s := range c.secrets { secret, err := c.secretLister.Secrets(c.namespace).Get(s.Name) switch { @@ -190,11 +199,14 @@ func (c *CertSyncController) sync() error { // remove missing content if err := os.RemoveAll(getSecretDir(c.destinationDir, s.Name)); err != nil { + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed removing file for secret: %s/%s: %v", secret.Namespace, secret.Name, err) errors = append(errors, err) } + c.eventRecorder.Warningf("CertificateRemoved", "Removed file for secret: %s/%s", secret.Namespace, secret.Name, err) continue case err != nil: + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed getting secret: %s/%s: %v", secret.Namespace, secret.Name, err) errors = append(errors, err) continue } @@ -227,6 +239,7 @@ func (c *CertSyncController) sync() error { secret, err = c.secretGetter.Get(secret.Name, metav1.GetOptions{}) if err != nil { // Even if the error is not exists we will act on it when caches catch up + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed getting secret: %s/%s: %v", secret.Namespace, secret.Name, err) errors = append(errors, err) continue } @@ -239,6 +252,7 @@ func (c *CertSyncController) sync() error { klog.Infof("Creating directory %q ...", contentDir) if err := os.MkdirAll(contentDir, 0755); err != nil && !os.IsExist(err) { + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed creating directory for secret: %s/%s: %v", secret.Namespace, secret.Name, err) errors = append(errors, err) continue } @@ -252,10 +266,12 @@ func (c *CertSyncController) sync() error { klog.Infof("Writing secret manifest %q ...", fullFilename) if err := ioutil.WriteFile(fullFilename, content, 0644); err != nil { + c.eventRecorder.Warningf("CertificateUpdateFailed", "Failed writing file for secret: %s/%s: %v", secret.Namespace, secret.Name, err) errors = append(errors, err) continue } } + c.eventRecorder.Eventf("CertificateUpdated", "Wrote updated secret: %s/%s", secret.Namespace, secret.Name) } return utilerrors.NewAggregate(errors) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/installerstate/installer_state_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/installerstate/installer_state_controller.go new file mode 100644 index 0000000000..2bcc5f710a --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/installerstate/installer_state_controller.go @@ -0,0 +1,254 @@ +package installerstate + +import ( + "fmt" + "strings" + "time" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/informers" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog" + + operatorv1 "github.com/openshift/api/operator/v1" + + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +const installerStateControllerWorkQueueKey = "key" + +// maxToleratedPodPendingDuration is the maximum time we tolerate installer pod in pending state +var maxToleratedPodPendingDuration = 5 * time.Minute + +type InstallerStateController struct { + podsGetter corev1client.PodsGetter + eventsGetter corev1client.EventsGetter + queue workqueue.RateLimitingInterface + cachesToSync []cache.InformerSynced + targetNamespace string + operatorClient v1helpers.StaticPodOperatorClient + eventRecorder events.Recorder + + timeNowFn func() time.Time +} + +func NewInstallerStateController(kubeInformersForTargetNamespace informers.SharedInformerFactory, + podsGetter corev1client.PodsGetter, + eventsGetter corev1client.EventsGetter, + operatorClient v1helpers.StaticPodOperatorClient, + targetNamespace string, + recorder events.Recorder, +) *InstallerStateController { + c := &InstallerStateController{ + podsGetter: podsGetter, + eventsGetter: eventsGetter, + targetNamespace: targetNamespace, + operatorClient: operatorClient, + eventRecorder: recorder.WithComponentSuffix("installer-state-controller"), + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "InstallerStateController"), + timeNowFn: time.Now, + } + + c.cachesToSync = append(c.cachesToSync, kubeInformersForTargetNamespace.Core().V1().Pods().Informer().HasSynced) + kubeInformersForTargetNamespace.Core().V1().Pods().Informer().AddEventHandler(c.eventHandler()) + + return c +} + +func (c *InstallerStateController) eventHandler() cache.ResourceEventHandler { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { c.queue.Add(installerStateControllerWorkQueueKey) }, + UpdateFunc: func(old, new interface{}) { c.queue.Add(installerStateControllerWorkQueueKey) }, + DeleteFunc: func(obj interface{}) { c.queue.Add(installerStateControllerWorkQueueKey) }, + } +} + +// degradedConditionNames lists all supported condition types. +var degradedConditionNames = []string{ + "InstallerPodPendingDegraded", + "InstallerPodContainerWaitingDegraded", + "InstallerPodNetworkingDegraded", +} + +func (c *InstallerStateController) sync() error { + pods, err := c.podsGetter.Pods(c.targetNamespace).List(metav1.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{"app": "installer"}).String(), + }) + if err != nil { + return err + } + + // collect all startingObjects that are in pending state for longer than maxToleratedPodPendingDuration + pendingPods := []*v1.Pod{} + for _, pod := range pods.Items { + if pod.Status.Phase != v1.PodPending || pod.Status.StartTime == nil { + continue + } + if c.timeNowFn().Sub(pod.Status.StartTime.Time) >= maxToleratedPodPendingDuration { + pendingPods = append(pendingPods, pod.DeepCopy()) + } + } + + // in theory, there should never be two installer startingObjects pending as we don't roll new installer pod + // until the previous/existing pod has finished its job. + foundConditions := []operatorv1.OperatorCondition{} + foundConditions = append(foundConditions, c.handlePendingInstallerPods(pendingPods)...) + + // handle networking conditions that are based on events + networkConditions, err := c.handlePendingInstallerPodsNetworkEvents(pendingPods) + if err != nil { + return err + } + foundConditions = append(foundConditions, networkConditions...) + + updateConditionFuncs := []v1helpers.UpdateStaticPodStatusFunc{} + + // check the supported degraded foundConditions and check if any pending pod matching them. + for _, degradedConditionName := range degradedConditionNames { + // clean up existing foundConditions + updatedCondition := operatorv1.OperatorCondition{ + Type: degradedConditionName, + Status: operatorv1.ConditionFalse, + } + if condition := v1helpers.FindOperatorCondition(foundConditions, degradedConditionName); condition != nil { + updatedCondition = *condition + } + updateConditionFuncs = append(updateConditionFuncs, v1helpers.UpdateStaticPodConditionFn(updatedCondition)) + } + + if _, _, err := v1helpers.UpdateStaticPodStatus(c.operatorClient, updateConditionFuncs...); err != nil { + return err + } + + return nil +} + +func (c *InstallerStateController) handlePendingInstallerPodsNetworkEvents(pods []*v1.Pod) ([]operatorv1.OperatorCondition, error) { + conditions := []operatorv1.OperatorCondition{} + if len(pods) == 0 { + return conditions, nil + } + namespaceEvents, err := c.eventsGetter.Events(c.targetNamespace).List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + for _, event := range namespaceEvents.Items { + if event.InvolvedObject.Kind != "Pod" { + continue + } + if !strings.Contains(event.Message, "failed to create pod network") { + continue + } + for _, pod := range pods { + if pod.Name != event.InvolvedObject.Name { + continue + } + // If we already find the pod that is pending because of the networking problem, skip other pods. + // This will reduce the events we fire. + if v1helpers.FindOperatorCondition(conditions, "InstallerPodNetworkingDegraded") != nil { + break + } + condition := operatorv1.OperatorCondition{ + Type: "InstallerPodNetworkingDegraded", + Status: operatorv1.ConditionTrue, + Reason: event.Reason, + Message: fmt.Sprintf("Pod %q on node %q observed degraded networking: %s", pod.Name, pod.Spec.NodeName, event.Message), + } + conditions = append(conditions, condition) + c.eventRecorder.Warningf(condition.Reason, condition.Message) + } + } + return conditions, nil +} + +func (c *InstallerStateController) handlePendingInstallerPods(pods []*v1.Pod) []operatorv1.OperatorCondition { + conditions := []operatorv1.OperatorCondition{} + for _, pod := range pods { + // at this point we already know the pod is pending for longer than expected + pendingTime := c.timeNowFn().Sub(pod.Status.StartTime.Time) + + // the pod is in the pending state for longer than maxToleratedPodPendingDuration, report the reason and message + // as degraded condition for the operator. + if len(pod.Status.Reason) > 0 { + condition := operatorv1.OperatorCondition{ + Type: "InstallerPodPendingDegraded", + Reason: pod.Status.Reason, + Status: operatorv1.ConditionTrue, + Message: fmt.Sprintf("Pod %q on node %q is Pending for %s because %s", pod.Name, pod.Spec.NodeName, pendingTime, pod.Status.Message), + } + conditions = append(conditions, condition) + c.eventRecorder.Warningf(condition.Reason, condition.Message) + } + + // one or more containers are in waiting state for longer than maxToleratedPodPendingDuration, report the reason and message + // as degraded condition for the operator. + for _, containerStatus := range pod.Status.ContainerStatuses { + if containerStatus.State.Waiting == nil { + continue + } + if state := containerStatus.State.Waiting; len(state.Reason) > 0 { + condition := operatorv1.OperatorCondition{ + Type: "InstallerPodContainerWaitingDegraded", + Reason: state.Reason, + Status: operatorv1.ConditionTrue, + Message: fmt.Sprintf("Pod %q on node %q container %q is waiting for %s because %s", pod.Name, pod.Spec.NodeName, containerStatus.Name, pendingTime, state.Message), + } + conditions = append(conditions, condition) + c.eventRecorder.Warningf(condition.Reason, condition.Message) + } + } + } + + return conditions +} + +// Run starts the kube-apiserver and blocks until stopCh is closed. +func (c *InstallerStateController) Run(workers int, stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Infof("Starting InstallerStateController") + defer klog.Infof("Shutting down InstallerStateController") + if !cache.WaitForCacheSync(stopCh, c.cachesToSync...) { + return + } + + // doesn't matter what workers say, only start one. + go wait.Until(c.runWorker, time.Second, stopCh) + + // add time based trigger + go wait.Until(func() { c.queue.Add(installerStateControllerWorkQueueKey) }, time.Minute, stopCh) + + <-stopCh +} + +func (c *InstallerStateController) runWorker() { + for c.processNextWorkItem() { + } +} + +func (c *InstallerStateController) processNextWorkItem() bool { + dsKey, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(dsKey) + + err := c.sync() + if err == nil { + c.queue.Forget(dsKey) + return true + } + + utilruntime.HandleError(fmt.Errorf("%v failed with : %v", dsKey, err)) + c.queue.AddRateLimited(dsKey) + + return true +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/installerstate/installer_state_controller_test.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/installerstate/installer_state_controller_test.go new file mode 100644 index 0000000000..c6e39856ff --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/installerstate/installer_state_controller_test.go @@ -0,0 +1,177 @@ +package installerstate + +import ( + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apiserver/pkg/storage/names" + "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes/fake" + + operatorv1 "github.com/openshift/api/operator/v1" + + "github.com/openshift/library-go/pkg/operator/events/eventstesting" + "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +func newInstallerPod(name string, mutateStatusFn func(*corev1.PodStatus)) *corev1.Pod { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: "test", + Labels: map[string]string{"app": "installer"}, + }, + Spec: corev1.PodSpec{}, + Status: corev1.PodStatus{}, + } + mutateStatusFn(&pod.Status) + return pod +} + +func newInstallerPodNetworkEvent(mutateFn func(*corev1.Event)) *corev1.Event { + event := &corev1.Event{ + ObjectMeta: metav1.ObjectMeta{ + Name: names.SimpleNameGenerator.GenerateName("test"), + Namespace: "test", + }, + InvolvedObject: corev1.ObjectReference{ + Kind: "Pod", + Name: "installer-1", + }, + Reason: "FailedCreatePodSandBox", + Message: `'(combined from similar events): Failed create pod sandbox: rpc error: + code = Unknown desc = failed to create pod network sandbox k8s_installer-5-control-plane-1_openshift-kube-apiserver_900db7f3-d2ce-11e9-8fc8-005056be0641_0(121698f4862fd67157ca586cab18aefb048fe5d7b3bd87516098ac0e91a90a13): + Multus: Err adding pod to network "openshift-sdn": Multus: error in invoke Delegate + add - "openshift-sdn": failed to send CNI request: Post http://dummy/: dial unix + /var/run/openshift-sdn/cniserver/socket: connect: connection refused'`, + } + if mutateFn != nil { + mutateFn(event) + } + return event +} + +func TestInstallerStateController(t *testing.T) { + tests := []struct { + name string + startingObjects []runtime.Object + evalConditions func(t *testing.T, conditions []operatorv1.OperatorCondition) + }{ + { + name: "should report pending pod", + startingObjects: []runtime.Object{ + newInstallerPod("installer-1", func(status *corev1.PodStatus) { + status.Phase = corev1.PodPending + status.Reason = "PendingReason" + status.Message = "PendingMessage" + status.StartTime = &metav1.Time{Time: time.Now().Add(-(maxToleratedPodPendingDuration + 5*time.Minute))} + }), + }, + evalConditions: func(t *testing.T, conditions []operatorv1.OperatorCondition) { + podPendingCondition := v1helpers.FindOperatorCondition(conditions, "InstallerPodPendingDegraded") + if podPendingCondition.Status != operatorv1.ConditionTrue { + t.Errorf("expected InstallerPodPendingDegraded condition to be True") + } + podContainerWaitingCondition := v1helpers.FindOperatorCondition(conditions, "InstallerPodContainerWaitingDegraded") + if podContainerWaitingCondition.Status != operatorv1.ConditionFalse { + t.Errorf("expected InstallerPodPendingDegraded condition to be False") + } + }, + }, + { + name: "should report pod with failing networking", + startingObjects: []runtime.Object{ + newInstallerPod("installer-1", func(status *corev1.PodStatus) { + status.Phase = corev1.PodPending + status.Reason = "PendingReason" + status.Message = "PendingMessage" + status.StartTime = &metav1.Time{Time: time.Now().Add(-(maxToleratedPodPendingDuration + 5*time.Minute))} + }), + newInstallerPodNetworkEvent(nil), + newInstallerPodNetworkEvent(nil), + newInstallerPodNetworkEvent(nil), + }, + evalConditions: func(t *testing.T, conditions []operatorv1.OperatorCondition) { + podPendingCondition := v1helpers.FindOperatorCondition(conditions, "InstallerPodNetworkingDegraded") + if podPendingCondition.Status != operatorv1.ConditionTrue { + t.Errorf("expected InstallerPodNetworkingDegraded condition to be True") + } + }, + }, + { + name: "should report pending pod with waiting container", + startingObjects: []runtime.Object{ + newInstallerPod("installer-1", func(status *corev1.PodStatus) { + status.Phase = corev1.PodPending + status.Reason = "PendingReason" + status.Message = "PendingMessage" + status.StartTime = &metav1.Time{Time: time.Now().Add(-(maxToleratedPodPendingDuration + 5*time.Minute))} + status.ContainerStatuses = append(status.ContainerStatuses, corev1.ContainerStatus{Name: "test", State: corev1.ContainerState{Waiting: &corev1.ContainerStateWaiting{ + Reason: "PodInitializing", + Message: "initializing error", + }}}) + }), + }, + evalConditions: func(t *testing.T, conditions []operatorv1.OperatorCondition) { + podPendingCondition := v1helpers.FindOperatorCondition(conditions, "InstallerPodPendingDegraded") + if podPendingCondition.Status != operatorv1.ConditionTrue { + t.Errorf("expected InstallerPodPendingDegraded condition to be True") + } + podContainerWaitingCondition := v1helpers.FindOperatorCondition(conditions, "InstallerPodContainerWaitingDegraded") + if podContainerWaitingCondition.Status != operatorv1.ConditionTrue { + t.Errorf("expected InstallerPodPendingDegraded condition to be True") + } + }, + }, + { + name: "should report false when no pending startingObjects", + startingObjects: []runtime.Object{ + newInstallerPod("installer-1", func(status *corev1.PodStatus) { + status.Phase = corev1.PodRunning + status.StartTime = &metav1.Time{Time: time.Now().Add(-(maxToleratedPodPendingDuration + 5*time.Minute))} + }), + }, + evalConditions: func(t *testing.T, conditions []operatorv1.OperatorCondition) { + podPendingCondition := v1helpers.FindOperatorCondition(conditions, "InstallerPodPendingDegraded") + if podPendingCondition.Status != operatorv1.ConditionFalse { + t.Errorf("expected InstallerPodPendingDegraded condition to be False") + } + podContainerWaitingCondition := v1helpers.FindOperatorCondition(conditions, "InstallerPodContainerWaitingDegraded") + if podContainerWaitingCondition.Status != operatorv1.ConditionFalse { + t.Errorf("expected InstallerPodPendingDegraded condition to be False") + } + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + kubeClient := fake.NewSimpleClientset(tt.startingObjects...) + kubeInformers := informers.NewSharedInformerFactoryWithOptions(kubeClient, 1*time.Minute, informers.WithNamespace("test")) + stopCh := make(chan struct{}) + go kubeInformers.Start(stopCh) + defer close(stopCh) + + fakeStaticPodOperatorClient := v1helpers.NewFakeStaticPodOperatorClient(&operatorv1.StaticPodOperatorSpec{}, &operatorv1.StaticPodOperatorStatus{}, nil, nil) + eventRecorder := eventstesting.NewTestingEventRecorder(t) + controller := NewInstallerStateController(kubeInformers, kubeClient.CoreV1(), kubeClient.CoreV1(), fakeStaticPodOperatorClient, "test", eventRecorder) + if err := controller.sync(); err != nil { + t.Error(err) + return + } + + _, status, _, err := fakeStaticPodOperatorClient.GetOperatorState() + if err != nil { + t.Error(err) + return + } + if tt.evalConditions != nil { + tt.evalConditions(t, status.Conditions) + } + }) + } + +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/revision/revision_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/revision/revision_controller.go index 6071d035e3..f694da0e6d 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/revision/revision_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/revision/revision_controller.go @@ -193,7 +193,7 @@ func (c RevisionController) isLatestRevisionCurrent(revision int32) (bool, strin } if !equality.Semantic.DeepEqual(existingData, requiredData) { if klog.V(4) { - klog.Infof("secret %q changes for revision %d: %s", s.Name, revision, resourceapply.JSONPatch(existing, required)) + klog.Infof("Secret %q changes for revision %d: %s", s.Name, revision, resourceapply.JSONPatchSecret(existing, required)) } secretChanges = append(secretChanges, fmt.Sprintf("secret/%s has changed", s.Name)) } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go index f17b19871b..00db28341d 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/openshift/library-go/pkg/operator/loglevel" + "github.com/openshift/library-go/pkg/operator/staticpod/controller/installerstate" "github.com/openshift/library-go/pkg/operator/unsupportedconfigoverridescontroller" @@ -138,6 +139,7 @@ func (b *staticPodOperatorControllerBuilder) ToControllers() (*staticPodOperator configMapClient := v1helpers.CachedConfigMapGetter(b.kubeClient.CoreV1(), b.kubeInformers) secretClient := v1helpers.CachedSecretGetter(b.kubeClient.CoreV1(), b.kubeInformers) podClient := b.kubeClient.CoreV1() + eventsClient := b.kubeClient.CoreV1() operandInformers := b.kubeInformers.InformersFor(b.operandNamespace) clusterInformers := b.kubeInformers.InformersFor("") @@ -172,6 +174,14 @@ func (b *staticPodOperatorControllerBuilder) ToControllers() (*staticPodOperator b.certConfigMaps, b.certSecrets, ) + controllers.installerStateController = installerstate.NewInstallerStateController( + operandInformers, + podClient, + eventsClient, + b.staticPodOperatorClient, + b.operandNamespace, + eventRecorder, + ) } if len(b.operandName) > 0 { @@ -239,6 +249,9 @@ func (b *staticPodOperatorControllerBuilder) ToControllers() (*staticPodOperator if controllers.installerController == nil { errs = append(errs, fmt.Errorf("missing installerController; cannot proceed")) } + if controllers.installerStateController == nil { + errs = append(errs, fmt.Errorf("missing installerStateController; cannot proceed")) + } if controllers.staticPodStateController == nil { eventRecorder.Warning("StaticPodStateControllerMissing", "not enough information provided, not all functionality is present") } @@ -255,6 +268,7 @@ func (b *staticPodOperatorControllerBuilder) ToControllers() (*staticPodOperator type staticPodOperatorControllers struct { revisionController *revision.RevisionController installerController *installer.InstallerController + installerStateController *installerstate.InstallerStateController staticPodStateController *staticpodstate.StaticPodStateController pruneController *prune.PruneController nodeController *node.NodeController @@ -272,6 +286,7 @@ func (o *staticPodOperatorControllers) WithInstallerPodMutationFn(installerPodMu func (o *staticPodOperatorControllers) Run(stopCh <-chan struct{}) { go o.revisionController.Run(1, stopCh) go o.installerController.Run(1, stopCh) + go o.installerStateController.Run(1, stopCh) go o.staticPodStateController.Run(1, stopCh) go o.pruneController.Run(1, stopCh) go o.nodeController.Run(1, stopCh) diff --git a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go index 014585c551..dc336276e0 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/v1helpers/test_helpers.go @@ -73,7 +73,6 @@ func NewFakeStaticPodOperatorClient( } type fakeStaticPodOperatorClient struct { - fakeOperatorStatus *operatorv1.OperatorStatus fakeStaticPodOperatorSpec *operatorv1.StaticPodOperatorSpec fakeStaticPodOperatorStatus *operatorv1.StaticPodOperatorStatus resourceVersion string @@ -130,13 +129,29 @@ func (c *fakeStaticPodOperatorClient) UpdateStaticPodOperatorSpec(resourceVersio } func (c *fakeStaticPodOperatorClient) GetOperatorState() (*operatorv1.OperatorSpec, *operatorv1.OperatorStatus, string, error) { - return &c.fakeStaticPodOperatorSpec.OperatorSpec, &c.fakeStaticPodOperatorStatus.OperatorStatus, "", nil + return &c.fakeStaticPodOperatorSpec.OperatorSpec, &c.fakeStaticPodOperatorStatus.OperatorStatus, c.resourceVersion, nil } func (c *fakeStaticPodOperatorClient) UpdateOperatorSpec(string, *operatorv1.OperatorSpec) (spec *operatorv1.OperatorSpec, resourceVersion string, err error) { panic("not supported") } -func (c *fakeStaticPodOperatorClient) UpdateOperatorStatus(string, *operatorv1.OperatorStatus) (status *operatorv1.OperatorStatus, err error) { - panic("not supported") +func (c *fakeStaticPodOperatorClient) UpdateOperatorStatus(resourceVersion string, status *operatorv1.OperatorStatus) (*operatorv1.OperatorStatus, error) { + if c.resourceVersion != resourceVersion { + return nil, errors.NewConflict(schema.GroupResource{Group: operatorv1.GroupName, Resource: "TestOperatorConfig"}, "instance", fmt.Errorf("invalid resourceVersion")) + } + rv, err := strconv.Atoi(resourceVersion) + if err != nil { + return nil, err + } + c.resourceVersion = strconv.Itoa(rv + 1) + if c.triggerStatusUpdateError != nil { + staticPodStatus := c.fakeStaticPodOperatorStatus.DeepCopy() + staticPodStatus.OperatorStatus = *status + if err := c.triggerStatusUpdateError(resourceVersion, staticPodStatus); err != nil { + return nil, err + } + } + c.fakeStaticPodOperatorStatus.OperatorStatus = *status + return &c.fakeStaticPodOperatorStatus.OperatorStatus, nil } // NewFakeNodeLister returns a fake node lister suitable to use in node controller unit test diff --git a/vendor/github.com/openshift/library-go/test/e2e-encryption/encryption_test.go b/vendor/github.com/openshift/library-go/test/e2e-encryption/encryption_test.go new file mode 100644 index 0000000000..70c4c8770e --- /dev/null +++ b/vendor/github.com/openshift/library-go/test/e2e-encryption/encryption_test.go @@ -0,0 +1,550 @@ +package e2e + +import ( + "encoding/json" + "fmt" + "os" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" + "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" + apiserverv1 "k8s.io/apiserver/pkg/apis/config/v1" + "k8s.io/client-go/dynamic" + "k8s.io/client-go/kubernetes" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/retry" + "sigs.k8s.io/yaml" + + configv1 "github.com/openshift/api/config/v1" + operatorv1 "github.com/openshift/api/operator/v1" + configv1clientfake "github.com/openshift/client-go/config/clientset/versioned/fake" + configv1informers "github.com/openshift/client-go/config/informers/externalversions" + + "github.com/openshift/library-go/pkg/operator/encryption" + "github.com/openshift/library-go/pkg/operator/encryption/secrets" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/genericoperatorclient" + "github.com/openshift/library-go/pkg/operator/v1helpers" + "github.com/openshift/library-go/test/library" +) + +func TestEncryptionIntegration(tt *testing.T) { + // in terminal print logs immediately + var t T = tt + fi, _ := os.Stdin.Stat() + if (fi.Mode() & os.ModeCharDevice) != 0 { + t = fmtLogger{tt} + } + + stopCh := make(chan struct{}) + defer close(stopCh) + + component := strings.ToLower(library.GenerateNameForTest(tt, "")) + + kubeConfig, err := library.NewClientConfigForTest() + require.NoError(t, err) + + // kube clients + kubeClient, err := kubernetes.NewForConfig(kubeConfig) + require.NoError(t, err) + kubeInformers := v1helpers.NewKubeInformersForNamespaces(kubeClient, "openshift-config-managed") + apiextensionsClient, err := v1beta1.NewForConfig(kubeConfig) + require.NoError(t, err) + + // create ExtensionTest operator CRD + var operatorCRD apiextensionsv1beta1.CustomResourceDefinition + require.NoError(t, yaml.Unmarshal([]byte(encryptionTestOperatorCRD), &operatorCRD)) + crd, err := apiextensionsClient.CustomResourceDefinitions().Create(&operatorCRD) + if errors.IsAlreadyExists(err) { + t.Logf("CRD %s already existing, ignoring error", operatorCRD.Name) + } else { + require.NoError(t, err) + } + defer apiextensionsClient.CustomResourceDefinitions().Delete(crd.Name, &metav1.DeleteOptions{}) + + // create operator client and create instance with ManagementState="Managed" + operatorGVR := schema.GroupVersionResource{Group: operatorCRD.Spec.Group, Version: "v1", Resource: operatorCRD.Spec.Names.Plural} + operatorv1.GroupVersion.WithResource("encryptiontests") + operatorClient, operatorInformer, err := genericoperatorclient.NewClusterScopedOperatorClient(kubeConfig, operatorGVR) + dynamicClient, err := dynamic.NewForConfig(kubeConfig) + require.NoError(t, err) + err = wait.PollImmediate(time.Second, wait.ForeverTestTimeout, func() (bool, error) { + _, err := dynamicClient.Resource(operatorGVR).Create(&unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "operator.openshift.io/v1", + "kind": "EncryptionTest", + "metadata": map[string]interface{}{ + "name": "cluster", + }, + "spec": map[string]interface{}{ + "managementState": "Managed", + }, + }, + }, metav1.CreateOptions{}) + if err != nil && !errors.IsAlreadyExists(err) { + t.Logf("failed to create APIServer object: %v", err) + return false, nil + } + return true, nil + }) + require.NoError(t, err) + + // create APIServer clients + fakeConfigClient := configv1clientfake.NewSimpleClientset(&configv1.APIServer{ObjectMeta: metav1.ObjectMeta{Name: "cluster"}}) + fakeConfigInformer := configv1informers.NewSharedInformerFactory(fakeConfigClient, 10*time.Minute) + fakeApiServerClient := fakeConfigClient.ConfigV1().APIServers() + + // create controllers + eventRecorder := events.NewLoggingEventRecorder(component) + deployer := NewInstantDeployer(t, stopCh, kubeInformers, kubeClient.CoreV1(), fmt.Sprintf("encryption-config-%s", component)) + + controllers, err := encryption.NewControllers( + component, + deployer, + operatorClient, + fakeApiServerClient, + fakeConfigInformer.Config().V1().APIServers(), + kubeInformers, + deployer, // secret client wrapping kubeClient with encryption-config revision counting + kubeClient.Discovery(), + eventRecorder, + dynamicClient, + // some random low-cardinality GVRs: + schema.GroupResource{Group: "operator.openshift.io", Resource: "kubeapiservers"}, + schema.GroupResource{Group: "operator.openshift.io", Resource: "kubeschedulers"}, + ) + require.NoError(t, err) + + // launch controllers + fakeConfigInformer.Start(stopCh) + kubeInformers.Start(stopCh) + operatorInformer.Start(stopCh) + go controllers.Run(stopCh) + + waitForConfigEventuallyCond := func(cond func(s string) bool) { + t.Helper() + stopCh := time.After(wait.ForeverTestTimeout) + for { + c, err := deployer.WaitUntil(stopCh) + require.NoError(t, err) + err = deployer.Deploy() + require.NoError(t, err) + + got := toString(c) + t.Logf("Observed %s", got) + if cond(got) { + return + } + } + } + waitForConfigEventually := func(expected string) { + t.Helper() + waitForConfigEventuallyCond(func(got string) bool { + return expected == got + }) + } + waitForConfigs := func(ss ...string) { + t.Helper() + for _, expected := range ss { + c, err := deployer.Wait() + require.NoError(t, err) + got := toString(c) + t.Logf("Observed %s", got) + if expected != "*" && got != expected { + t.Fatalf("wrong EncryptionConfig:\n expected: %s\n got: %s", expected, got) + } + + err = deployer.Deploy() + require.NoError(t, err) + } + } + + t.Logf("Enable encryption, mode aescbc") + _, err = fakeApiServerClient.Patch("cluster", types.MergePatchType, []byte(`{"spec":{"encryption":{"type":"aescbc"}}}`)) + require.NoError(t, err) + + t.Logf("Waiting for key to show up") + keySecretsLabel := fmt.Sprintf("%s=%s", secrets.EncryptionKeySecretsLabel, component) + waitForKeys := func(n int) { + t.Helper() + err := wait.PollImmediate(time.Second, wait.ForeverTestTimeout, func() (bool, error) { + l, err := kubeClient.CoreV1().Secrets("openshift-config-managed").List(metav1.ListOptions{LabelSelector: keySecretsLabel}) + if err != nil { + return false, err + } + if len(l.Items) == n { + return true, nil + } + t.Logf("Seeing %d secrets, waiting for %d", len(l.Items), n) + return false, nil + }) + require.NoError(t, err) + } + waitForKeys(1) + waitForConfigs( + "kubeapiservers.operator.openshift.io=identity,aescbc:1;kubeschedulers.operator.openshift.io=identity,aescbc:1", + "kubeapiservers.operator.openshift.io=aescbc:1,identity;kubeschedulers.operator.openshift.io=aescbc:1,identity", + ) + + t.Logf("Switch to identity") + _, err = fakeApiServerClient.Patch("cluster", types.MergePatchType, []byte(`{"spec":{"encryption":{"type":"identity"}}}`)) + require.NoError(t, err) + waitForKeys(2) + waitForConfigs( + "kubeapiservers.operator.openshift.io=aescbc:1,identity,aesgcm:2;kubeschedulers.operator.openshift.io=aescbc:1,identity,aesgcm:2", + "kubeapiservers.operator.openshift.io=identity,aescbc:1,aesgcm:2;kubeschedulers.operator.openshift.io=identity,aescbc:1,aesgcm:2", + "kubeapiservers.operator.openshift.io=identity,aesgcm:2;kubeschedulers.operator.openshift.io=identity,aesgcm:2", + ) + + t.Logf("Switch to empty mode") + _, err = fakeApiServerClient.Patch("cluster", types.MergePatchType, []byte(`{"spec":{"encryption":{"type":""}}}`)) + require.NoError(t, err) + time.Sleep(5 * time.Second) + waitForKeys(2) + + t.Logf("Switch to aescbc again") + _, err = fakeApiServerClient.Patch("cluster", types.MergePatchType, []byte(`{"spec":{"encryption":{"type":"aescbc"}}}`)) + require.NoError(t, err) + waitForKeys(3) + waitForConfigs( + "kubeapiservers.operator.openshift.io=identity,aescbc:3,aesgcm:2;kubeschedulers.operator.openshift.io=identity,aescbc:3,aesgcm:2", + "kubeapiservers.operator.openshift.io=aescbc:3,identity,aesgcm:2;kubeschedulers.operator.openshift.io=aescbc:3,identity,aesgcm:2", + "kubeapiservers.operator.openshift.io=aescbc:3,identity;kubeschedulers.operator.openshift.io=aescbc:3,identity", + ) + + t.Logf("Setting external reason") + setExternalReason := func(reason string) { + t.Helper() + err = retry.RetryOnConflict(retry.DefaultBackoff, func() error { + spec, _, rv, err := operatorClient.GetOperatorState() + if err != nil { + return err + } + spec.UnsupportedConfigOverrides.Raw = []byte(fmt.Sprintf(`{"encryption":{"reason":%q}}`, reason)) + _, _, err = operatorClient.UpdateOperatorSpec(rv, spec) + return err + }) + require.NoError(t, err) + } + setExternalReason("a") + waitForKeys(4) + waitForConfigs( + "kubeapiservers.operator.openshift.io=aescbc:3,aescbc:4,identity;kubeschedulers.operator.openshift.io=aescbc:3,aescbc:4,identity", + "kubeapiservers.operator.openshift.io=aescbc:4,aescbc:3,identity;kubeschedulers.operator.openshift.io=aescbc:4,aescbc:3,identity", + "kubeapiservers.operator.openshift.io=aescbc:4,identity;kubeschedulers.operator.openshift.io=aescbc:4,identity", + ) + + t.Logf("Setting another external reason") + setExternalReason("b") + waitForKeys(5) + waitForConfigs( + "kubeapiservers.operator.openshift.io=aescbc:4,aescbc:5,identity;kubeschedulers.operator.openshift.io=aescbc:4,aescbc:5,identity", + "kubeapiservers.operator.openshift.io=aescbc:5,aescbc:4,identity;kubeschedulers.operator.openshift.io=aescbc:5,aescbc:4,identity", + "kubeapiservers.operator.openshift.io=aescbc:5,identity;kubeschedulers.operator.openshift.io=aescbc:5,identity", + ) + + t.Logf("Expire the last key") + _, err = kubeClient.CoreV1().Secrets("openshift-config-managed").Patch(fmt.Sprintf("encryption-key-%s-5", component), types.MergePatchType, []byte(`{"metadata":{"annotations":{"encryption.apiserver.operator.openshift.io/migrated-timestamp":"2010-10-17T14:14:52+02:00"}}}`)) + require.NoError(t, err) + waitForKeys(6) + waitForConfigs( + "kubeapiservers.operator.openshift.io=aescbc:5,aescbc:6,identity;kubeschedulers.operator.openshift.io=aescbc:5,aescbc:6,identity", + "kubeapiservers.operator.openshift.io=aescbc:6,aescbc:5,identity;kubeschedulers.operator.openshift.io=aescbc:6,aescbc:5,identity", + "kubeapiservers.operator.openshift.io=aescbc:6,identity;kubeschedulers.operator.openshift.io=aescbc:6,identity", + ) + + t.Logf("Delete the last key") + _, err = kubeClient.CoreV1().Secrets("openshift-config-managed").Patch(fmt.Sprintf("encryption-key-%s-6", component), types.JSONPatchType, []byte(`[{"op":"remove","path":"/metadata/finalizers"}]`)) + require.NoError(t, err) + err = kubeClient.CoreV1().Secrets("openshift-config-managed").Delete(fmt.Sprintf("encryption-key-%s-6", component), nil) + require.NoError(t, err) + err = wait.PollImmediate(time.Second, wait.ForeverTestTimeout, func() (bool, error) { + _, err := kubeClient.CoreV1().Secrets("openshift-config-managed").Get(fmt.Sprintf("encryption-key-%s-7", component), metav1.GetOptions{}) + if errors.IsNotFound(err) { + return false, nil + } + return err == nil, nil + }) + require.NoError(t, err) + // here we see potentially also the following if the key controller is slower than the state controller: + // kubeapiservers.operator.openshift.io=aescbc:6,aescbc:5,identity;kubeschedulers.operator.openshift.io=aescbc:6,aescbc:5,identity + // but eventually we get the following: + waitForConfigEventually( + // 6 as preserved config key, 7 as newly created key, and 5 as fully migrated key + "kubeapiservers.operator.openshift.io=aescbc:6,aescbc:7,aescbc:5,identity;kubeschedulers.operator.openshift.io=aescbc:6,aescbc:7,aescbc:5,identity", + ) + waitForConfigs( + "kubeapiservers.operator.openshift.io=aescbc:7,aescbc:6,aescbc:5,identity;kubeschedulers.operator.openshift.io=aescbc:7,aescbc:6,aescbc:5,identity", + "kubeapiservers.operator.openshift.io=aescbc:7,identity;kubeschedulers.operator.openshift.io=aescbc:7,identity", + ) + + t.Logf("Delete the openshift-config-managed config") + _, err = kubeClient.CoreV1().Secrets("openshift-config-managed").Patch(fmt.Sprintf("encryption-config-%s", component), types.JSONPatchType, []byte(`[{"op":"remove","path":"/metadata/finalizers"}]`)) + require.NoError(t, err) + err = kubeClient.CoreV1().Secrets("openshift-config-managed").Delete(fmt.Sprintf("encryption-config-%s", component), nil) + require.NoError(t, err) + waitForConfigs( + "kubeapiservers.operator.openshift.io=aescbc:7,identity;kubeschedulers.operator.openshift.io=aescbc:7,identity", + ) + + t.Logf("Delete the openshift-config-managed config") + deployer.DeleteOperandConfig() + waitForConfigs( + // 7 is migrated and hence only one needed, but we rotate through identity + "kubeapiservers.operator.openshift.io=identity,aescbc:7;kubeschedulers.operator.openshift.io=identity,aescbc:7", + "kubeapiservers.operator.openshift.io=aescbc:7,identity;kubeschedulers.operator.openshift.io=aescbc:7,identity", + ) +} + +const encryptionTestOperatorCRD = ` +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: encryptiontests.operator.openshift.io +spec: + group: operator.openshift.io + names: + kind: EncryptionTest + listKind: EncryptionTestList + plural: encryptiontests + singular: encryptiontest + scope: Cluster + subresources: + status: {} + versions: + - name: v1 + served: true + storage: true +` + +func toString(c *apiserverv1.EncryptionConfiguration) string { + rs := make([]string, 0, len(c.Resources)) + for _, r := range c.Resources { + ps := make([]string, 0, len(r.Providers)) + for _, p := range r.Providers { + var s string + switch { + case p.AESCBC != nil: + s = "aescbc:" + p.AESCBC.Keys[0].Name + case p.AESGCM != nil: + s = "aesgcm:" + p.AESGCM.Keys[0].Name + case p.Identity != nil: + s = "identity" + } + ps = append(ps, s) + } + rs = append(rs, fmt.Sprintf("%s=%s", strings.Join(r.Resources, ","), strings.Join(ps, ","))) + } + return strings.Join(rs, ";") +} + +func NewInstantDeployer(t T, stopCh <-chan struct{}, kubeInformers v1helpers.KubeInformersForNamespaces, secretsClient corev1client.SecretsGetter, + secretName string) *lockStepDeployer { + return &lockStepDeployer{ + kubeInformers: kubeInformers, + secretsClient: secretsClient, + stopCh: stopCh, + configManagedSecretsClient: secretInterceptor{ + t: t, + output: make(chan *corev1.Secret), + SecretInterface: secretsClient.Secrets("openshift-config-managed"), + secretName: secretName, + }, + } +} + +// lockStepDeployer mirrors the encryption-config each time Deploy() is called. +// After Deploy() a call to Wait() is necessary. +type lockStepDeployer struct { + stopCh <-chan struct{} + + kubeInformers v1helpers.KubeInformersForNamespaces + secretsClient corev1client.SecretsGetter + configManagedSecretsClient secretInterceptor + + lock sync.Mutex + next *corev1.Secret + current *corev1.Secret + handlers []cache.ResourceEventHandler +} + +func (d *lockStepDeployer) Wait() (*apiserverv1.EncryptionConfiguration, error) { + return d.WaitUntil(nil) +} + +func (d *lockStepDeployer) WaitUntil(stopCh <-chan time.Time) (*apiserverv1.EncryptionConfiguration, error) { + d.lock.Lock() + if d.next != nil { + d.lock.Unlock() + return nil, fmt.Errorf("next secret already set. Forgotten Deploy call?") + } + d.lock.Unlock() + + select { + case s := <-d.configManagedSecretsClient.output: + var c apiserverv1.EncryptionConfiguration + if err := json.Unmarshal(s.Data["encryption-config"], &c); err != nil { + return nil, fmt.Errorf("failed to unmarshal encryption secret: %v", err) + } + + d.lock.Lock() + defer d.lock.Unlock() + d.next = s + + return &c, nil + case <-stopCh: + return nil, fmt.Errorf("timeout") + case <-d.stopCh: + return nil, fmt.Errorf("terminating") + } +} + +func (d *lockStepDeployer) Deploy() error { + d.lock.Lock() + + if d.next == nil { + d.lock.Unlock() + return fmt.Errorf("no next secret available") + } + + old := d.current + d.current = d.next + d.next = nil + + handlers := make([]cache.ResourceEventHandler, len(d.handlers)) + copy(handlers, d.handlers) + + d.lock.Unlock() + + for _, h := range handlers { + if old == nil { + h.OnAdd(d.current) + } else { + h.OnUpdate(old, d.current) + } + } + + return nil +} + +func (d *lockStepDeployer) Secrets(namespace string) corev1client.SecretInterface { + if namespace == "openshift-config-managed" { + return &d.configManagedSecretsClient + } + return d.secretsClient.Secrets(namespace) +} + +type secretInterceptor struct { + corev1client.SecretInterface + + t T + output chan *corev1.Secret + secretName string +} + +func (c *secretInterceptor) Create(s *corev1.Secret) (*corev1.Secret, error) { + s, err := c.SecretInterface.Create(s) + if err != nil { + return s, err + } + + c.t.Logf("Create", s.Name) + if s.Name == c.secretName { + c.output <- s + } + + return s, nil +} + +func (c *secretInterceptor) Update(s *corev1.Secret) (*corev1.Secret, error) { + s, err := c.SecretInterface.Update(s) + if err != nil { + return s, err + } + + c.t.Logf("Update", s.Name) + if s.Name == c.secretName { + c.output <- s + } + + return s, nil +} + +func (c *secretInterceptor) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *corev1.Secret, err error) { + s, err := c.SecretInterface.Patch(name, pt, data, subresources...) + if err != nil { + return s, err + } + + c.t.Logf("Patch", s.Name) + if s.Name == c.secretName { + c.output <- s + } + + return s, nil +} + +func (d *lockStepDeployer) AddEventHandler(handler cache.ResourceEventHandler) []cache.InformerSynced { + d.lock.Lock() + defer d.lock.Unlock() + + d.handlers = append(d.handlers, handler) + + return []cache.InformerSynced{} +} + +func (d *lockStepDeployer) DeployedEncryptionConfigSecret() (secret *corev1.Secret, converged bool, err error) { + d.lock.Lock() + defer d.lock.Unlock() + + return d.current, true, nil +} + +func (d *lockStepDeployer) DeleteOperandConfig() { + d.lock.Lock() + old := d.current + d.current = nil + d.next = nil + handlers := make([]cache.ResourceEventHandler, len(d.handlers)) + copy(handlers, d.handlers) + d.lock.Unlock() + + for _, h := range handlers { + h.OnDelete(old) + } +} + +type T interface { + require.TestingT + Logf(format string, args ...interface{}) + Fatalf(format string, args ...interface{}) + Helper() +} + +type fmtLogger struct { + *testing.T +} + +func (l fmtLogger) Errorf(format string, args ...interface{}) { + l.T.Helper() + fmt.Printf(format+"\n", args...) + l.T.Errorf(format, args...) +} + +func (l fmtLogger) Logf(format string, args ...interface{}) { + l.T.Helper() + fmt.Printf("STEP: "+format+"\n", args...) + l.T.Logf(format, args...) +} diff --git a/vendor/github.com/openshift/library-go/test/library/client.go b/vendor/github.com/openshift/library-go/test/library/client.go new file mode 100644 index 0000000000..06f6192b21 --- /dev/null +++ b/vendor/github.com/openshift/library-go/test/library/client.go @@ -0,0 +1,19 @@ +package library + +import ( + "fmt" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" +) + +// NewClientConfigForTest returns a config configured to connect to the api server +func NewClientConfigForTest() (*rest.Config, error) { + loader := clientcmd.NewDefaultClientConfigLoadingRules() + clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loader, &clientcmd.ConfigOverrides{ClusterInfo: api.Cluster{InsecureSkipTLSVerify: true}}) + config, err := clientConfig.ClientConfig() + if err == nil { + fmt.Printf("Found configuration for host %v.\n", config.Host) + } + return config, err +} diff --git a/vendor/github.com/openshift/library-go/test/library/library.go b/vendor/github.com/openshift/library-go/test/library/library.go new file mode 100644 index 0000000000..e09acc6437 --- /dev/null +++ b/vendor/github.com/openshift/library-go/test/library/library.go @@ -0,0 +1,34 @@ +package library + +import ( + "crypto/rand" + "fmt" + "math" + "math/big" + "regexp" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +var ( + WaitPollInterval = time.Second + WaitPollTimeout = 10 * time.Minute +) + +// GenerateNameForTest generates a name of the form `prefix + test name + random string` that +// can be used as a resource name. Convert the result to lowercase to use as a dns label. +func GenerateNameForTest(t *testing.T, prefix string) string { + n, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) + require.NoError(t, err) + name := []byte(fmt.Sprintf("%s%s-%016x", prefix, t.Name(), n.Int64())) + // make the name (almost) suitable for use as a dns label + // only a-z, 0-9, and '-' allowed + name = regexp.MustCompile("[^a-zA-Z0-9]+").ReplaceAll(name, []byte("-")) + // collapse multiple `-` + name = regexp.MustCompile("-+").ReplaceAll(name, []byte("-")) + // ensure no `-` at beginning or end + return strings.Trim(string(name), "-") +} diff --git a/vendor/github.com/spf13/cobra/.gitignore b/vendor/github.com/spf13/cobra/.gitignore index b2b848e77c..1b8c7c2611 100644 --- a/vendor/github.com/spf13/cobra/.gitignore +++ b/vendor/github.com/spf13/cobra/.gitignore @@ -32,8 +32,5 @@ Session.vim tags *.exe -cobra -cobra.test -.idea/ -*.iml +cobra.test diff --git a/vendor/github.com/spf13/cobra/.travis.yml b/vendor/github.com/spf13/cobra/.travis.yml index fca1e69488..38b85f499c 100644 --- a/vendor/github.com/spf13/cobra/.travis.yml +++ b/vendor/github.com/spf13/cobra/.travis.yml @@ -18,10 +18,13 @@ matrix: go: 1.12.x script: diff -u <(echo -n) <(gofmt -d -s .) -before_install: go get -u github.com/kyoh86/richgo - +before_install: + - mkdir -p bin + - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.6.0/shellcheck + - chmod +x bin/shellcheck + - go get -u github.com/kyoh86/richgo script: - - richgo test -v ./... + - PATH=$PATH:$PWD/bin richgo test -v ./... - go build - if [ -z $NOVET ]; then diff -u <(echo -n) <(go vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint'); diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 649e2e2f75..ff16e3f60d 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -23,8 +23,6 @@ Many of the most widely used Go projects are built using Cobra, such as: [Istio](https://istio.io), [Prototool](https://github.com/uber/prototool), [mattermost-server](https://github.com/mattermost/mattermost-server), -[Gardener](https://github.com/gardener/gardenctl), -[Linkerd](https://linkerd.io/), etc. [![Build Status](https://travis-ci.org/spf13/cobra.svg "Travis CI status")](https://travis-ci.org/spf13/cobra) @@ -50,7 +48,6 @@ etc. * [Suggestions when "unknown command" happens](#suggestions-when-unknown-command-happens) * [Generating documentation for your command](#generating-documentation-for-your-command) * [Generating bash completions](#generating-bash-completions) - * [Generating zsh completions](#generating-zsh-completions) - [Contributing](#contributing) - [License](#license) @@ -218,8 +215,6 @@ import ( "github.com/spf13/viper" ) -var cfgFile string - func init() { cobra.OnInitialize(initConfig) rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)") @@ -341,7 +336,7 @@ rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose out A flag can also be assigned locally which will only apply to that specific command. ```go -localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") +rootCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from") ``` ### Local Flag on Parent Commands @@ -724,11 +719,6 @@ Cobra can generate documentation based on subcommands, flags, etc. in the follow Cobra can generate a bash-completion file. If you add more information to your command, these completions can be amazingly powerful and flexible. Read more about it in [Bash Completions](bash_completions.md). -## Generating zsh completions - -Cobra can generate zsh-completion file. Read more about it in -[Zsh Completions](zsh_completions.md). - # Contributing 1. Fork it diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 03ddda27a3..c3c1e50188 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -72,9 +72,7 @@ __%[1]s_handle_reply() else allflags=("${flags[*]} ${two_word_flags[*]}") fi - while IFS='' read -r c; do - COMPREPLY+=("$c") - done < <(compgen -W "${allflags[*]}" -- "$cur") + COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") ) if [[ $(type -t compopt) = "builtin" ]]; then [[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace fi @@ -124,14 +122,10 @@ __%[1]s_handle_reply() if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then completions+=("${must_have_one_flag[@]}") fi - while IFS='' read -r c; do - COMPREPLY+=("$c") - done < <(compgen -W "${completions[*]}" -- "$cur") + COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") ) if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then - while IFS='' read -r c; do - COMPREPLY+=("$c") - done < <(compgen -W "${noun_aliases[*]}" -- "$cur") + COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") ) fi if [[ ${#COMPREPLY[@]} -eq 0 ]]; then @@ -166,7 +160,7 @@ __%[1]s_handle_filename_extension_flag() __%[1]s_handle_subdirs_in_dir_flag() { local dir="$1" - pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return + pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 } __%[1]s_handle_flag() @@ -551,3 +545,51 @@ func (c *Command) GenBashCompletionFile(filename string) error { return c.GenBashCompletion(outFile) } + +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkFlagRequired(name string) error { + return MarkFlagRequired(c.Flags(), name) +} + +// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag if it exists, +// and causes your command to report an error if invoked without the flag. +func (c *Command) MarkPersistentFlagRequired(name string) error { + return MarkFlagRequired(c.PersistentFlags(), name) +} + +// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, +// and causes your command to report an error if invoked without the flag. +func MarkFlagRequired(flags *pflag.FlagSet, name string) error { + return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) +} + +// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. +// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. +func (c *Command) MarkFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.Flags(), name, extensions...) +} + +// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. +// Generated bash autocompletion will call the bash function f for the flag. +func (c *Command) MarkFlagCustom(name string, f string) error { + return MarkFlagCustom(c.Flags(), name, f) +} + +// MarkPersistentFlagFilename adds the BashCompFilenameExt annotation to the named persistent flag, if it exists. +// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. +func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { + return MarkFlagFilename(c.PersistentFlags(), name, extensions...) +} + +// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag in the flag set, if it exists. +// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. +func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { + return flags.SetAnnotation(name, BashCompFilenameExt, extensions) +} + +// MarkFlagCustom adds the BashCompCustom annotation to the named flag in the flag set, if it exists. +// Generated bash autocompletion will call the bash function f for the flag. +func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error { + return flags.SetAnnotation(name, BashCompCustom, []string{f}) +} diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index d01becc8fa..6505c070b4 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -52,7 +52,7 @@ var EnableCommandSorting = true // if the CLI is started from explorer.exe. // To disable the mousetrap, just set this variable to blank string (""). // Works only on Microsoft Windows. -var MousetrapHelpText = `This is a command line tool. +var MousetrapHelpText string = `This is a command line tool. You need to open cmd.exe and run it from there. ` @@ -61,7 +61,7 @@ You need to open cmd.exe and run it from there. // if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed. // To disable the mousetrap, just set MousetrapHelpText to blank string (""). // Works only on Microsoft Windows. -var MousetrapDisplayDuration = 5 * time.Second +var MousetrapDisplayDuration time.Duration = 5 * time.Second // AddTemplateFunc adds a template function that's available to Usage and Help // template generation. diff --git a/vendor/github.com/spf13/cobra/cobra/README.md b/vendor/github.com/spf13/cobra/cobra/README.md index c360fdaca3..6054f95c52 100644 --- a/vendor/github.com/spf13/cobra/cobra/README.md +++ b/vendor/github.com/spf13/cobra/cobra/README.md @@ -16,23 +16,11 @@ for you. It is a very powerful application that will populate your program with the right structure so you can immediately enjoy all the benefits of Cobra. It will also automatically apply the license you specify to your application. -Cobra init is pretty smart. You can either run it in your current application directory -or you can specify a relative path to an existing project. If the directory does not exist, it will be created for you. - -Updates to the Cobra generator have now decoupled it from the GOPATH. -As such `--pkg-name` is required. - -**Note:** init will no longer fail on non-empty directories. - -``` -mkdir -p newApp && cd newApp -cobra init --pkg-name github.com/spf13/newApp -``` - -or +Cobra init is pretty smart. You can provide it a full path, or simply a path +similar to what is expected in the import. ``` -cobra init --pkg-name github.com/spf13/newApp path/to/newApp +cobra init github.com/spf13/newApp ``` ### cobra add diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/add.go b/vendor/github.com/spf13/cobra/cobra/cmd/add.go index 6645a755f0..fb22096a39 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/add.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/add.go @@ -16,20 +16,24 @@ package cmd import ( "fmt" "os" + "path/filepath" "unicode" "github.com/spf13/cobra" ) -var ( - packageName string - parentName string +func init() { + addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)") + addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command") +} + +var packageName, parentName string - addCmd = &cobra.Command{ - Use: "add [command name]", - Aliases: []string{"command"}, - Short: "Add a command to a Cobra Application", - Long: `Add (cobra add) will create a new command, with a license and +var addCmd = &cobra.Command{ + Use: "add [command name]", + Aliases: []string{"command"}, + Short: "Add a command to a Cobra Application", + Long: `Add (cobra add) will create a new command, with a license and the appropriate structure for a Cobra-based CLI application, and register it to its parent (default rootCmd). @@ -38,41 +42,28 @@ with an initial uppercase letter. Example: cobra add server -> resulting in a new cmd/server.go`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) < 1 { - er("add needs a name for the command") - } + Run: func(cmd *cobra.Command, args []string) { + if len(args) < 1 { + er("add needs a name for the command") + } + var project *Project + if packageName != "" { + project = NewProject(packageName) + } else { wd, err := os.Getwd() if err != nil { er(err) } + project = NewProjectFromPath(wd) + } - commandName := validateCmdName(args[0]) - command := &Command{ - CmdName: commandName, - CmdParent: parentName, - Project: &Project{ - AbsolutePath: wd, - Legal: getLicense(), - Copyright: copyrightLine(), - }, - } - - err = command.Create() - if err != nil { - er(err) - } - - fmt.Printf("%s created at %s\n", command.CmdName, command.AbsolutePath) - }, - } -) + cmdName := validateCmdName(args[0]) + cmdPath := filepath.Join(project.CmdPath(), cmdName+".go") + createCmdFile(project.License(), cmdPath, cmdName) -func init() { - addCmd.Flags().StringVarP(&packageName, "package", "t", "", "target package name (e.g. github.com/spf13/hugo)") - addCmd.Flags().StringVarP(&parentName, "parent", "p", "rootCmd", "variable name of parent command for this command") - addCmd.Flags().MarkDeprecated("package", "this operation has been removed.") + fmt.Fprintln(cmd.OutOrStdout(), cmdName, "created at", cmdPath) + }, } // validateCmdName returns source without any dashes and underscore. @@ -127,3 +118,62 @@ func validateCmdName(source string) string { } return output } + +func createCmdFile(license License, path, cmdName string) { + template := `{{comment .copyright}} +{{if .license}}{{comment .license}}{{end}} + +package {{.cmdPackage}} + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// {{.cmdName}}Cmd represents the {{.cmdName}} command +var {{.cmdName}}Cmd = &cobra.Command{ + Use: "{{.cmdName}}", + Short: "A brief description of your command", + Long: ` + "`" + `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.` + "`" + `, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("{{.cmdName}} called") + }, +} + +func init() { + {{.parentName}}.AddCommand({{.cmdName}}Cmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // {{.cmdName}}Cmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // {{.cmdName}}Cmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} +` + + data := make(map[string]interface{}) + data["copyright"] = copyrightLine() + data["license"] = license.Header + data["cmdPackage"] = filepath.Base(filepath.Dir(path)) // last dir of path + data["parentName"] = parentName + data["cmdName"] = cmdName + + cmdScript, err := executeTemplate(template, data) + if err != nil { + er(err) + } + err = writeStringToFile(path, cmdScript) + if err != nil { + er(err) + } +} diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/add_test.go b/vendor/github.com/spf13/cobra/cobra/cmd/add_test.go index de92fcea66..b920e2b9df 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/add_test.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/add_test.go @@ -1,28 +1,85 @@ package cmd import ( - "fmt" + "errors" + "io/ioutil" "os" + "path/filepath" "testing" + + "github.com/spf13/viper" ) +// TestGoldenAddCmd initializes the project "github.com/spf13/testproject" +// in GOPATH, adds "test" command +// and compares the content of all files in cmd directory of testproject +// with appropriate golden files. +// Use -update to update existing golden files. func TestGoldenAddCmd(t *testing.T) { - command := &Command{ - CmdName: "test", - CmdParent: parentName, - Project: getProject(), - } - defer os.RemoveAll(command.AbsolutePath) + projectName := "github.com/spf13/testproject" + project := NewProject(projectName) + defer os.RemoveAll(project.AbsPath()) + + viper.Set("author", "NAME HERE ") + viper.Set("license", "apache") + viper.Set("year", 2017) + defer viper.Set("author", nil) + defer viper.Set("license", nil) + defer viper.Set("year", nil) + + // Initialize the project first. + initializeProject(project) - command.Project.Create() - if err := command.Create(); err != nil { + // Then add the "test" command. + cmdName := "test" + cmdPath := filepath.Join(project.CmdPath(), cmdName+".go") + createCmdFile(project.License(), cmdPath, cmdName) + + expectedFiles := []string{".", "root.go", "test.go"} + gotFiles := []string{} + + // Check project file hierarchy and compare the content of every single file + // with appropriate golden file. + err := filepath.Walk(project.CmdPath(), func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Make path relative to project.CmdPath(). + // E.g. path = "/home/user/go/src/github.com/spf13/testproject/cmd/root.go" + // then it returns just "root.go". + relPath, err := filepath.Rel(project.CmdPath(), path) + if err != nil { + return err + } + relPath = filepath.ToSlash(relPath) + gotFiles = append(gotFiles, relPath) + goldenPath := filepath.Join("testdata", filepath.Base(path)+".golden") + + switch relPath { + // Known directories. + case ".": + return nil + // Known files. + case "root.go", "test.go": + if *update { + got, err := ioutil.ReadFile(path) + if err != nil { + return err + } + ioutil.WriteFile(goldenPath, got, 0644) + } + return compareFiles(path, goldenPath) + } + // Unknown file. + return errors.New("unknown file: " + path) + }) + if err != nil { t.Fatal(err) } - generatedFile := fmt.Sprintf("%s/cmd/%s.go", command.AbsolutePath, command.CmdName) - goldenFile := fmt.Sprintf("testdata/%s.go.golden", command.CmdName) - err := compareFiles(generatedFile, goldenFile) - if err != nil { + // Check if some files lack. + if err := checkLackFiles(expectedFiles, gotFiles); err != nil { t.Fatal(err) } } diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/init.go b/vendor/github.com/spf13/cobra/cobra/cmd/init.go index dcf5ada4fb..d65e6c8c59 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/init.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/init.go @@ -17,19 +17,17 @@ import ( "fmt" "os" "path" + "path/filepath" "github.com/spf13/cobra" "github.com/spf13/viper" ) -var ( - pkgName string - - initCmd = &cobra.Command{ - Use: "init [name]", - Aliases: []string{"initialize", "initialise", "create"}, - Short: "Initialize a Cobra Application", - Long: `Initialize (cobra init) will create a new application, with a license +var initCmd = &cobra.Command{ + Use: "init [name]", + Aliases: []string{"initialize", "initialise", "create"}, + Short: "Initialize a Cobra Application", + Long: `Initialize (cobra init) will create a new application, with a license and the appropriate structure for a Cobra-based CLI application. * If a name is provided, it will be created in the current directory; @@ -41,38 +39,196 @@ and the appropriate structure for a Cobra-based CLI application. Init will not use an existing directory with contents.`, - Run: func(cmd *cobra.Command, args []string) { + Run: func(cmd *cobra.Command, args []string) { + wd, err := os.Getwd() + if err != nil { + er(err) + } - wd, err := os.Getwd() - if err != nil { - er(err) + var project *Project + if len(args) == 0 { + project = NewProjectFromPath(wd) + } else if len(args) == 1 { + arg := args[0] + if arg[0] == '.' { + arg = filepath.Join(wd, arg) } - - if len(args) > 0 { - if args[0] != "." { - wd = fmt.Sprintf("%s/%s", wd, args[0]) - } + if filepath.IsAbs(arg) { + project = NewProjectFromPath(arg) + } else { + project = NewProject(arg) } + } else { + er("please provide only one argument") + } - project := &Project{ - AbsolutePath: wd, - PkgName: pkgName, - Legal: getLicense(), - Copyright: copyrightLine(), - Viper: viper.GetBool("useViper"), - AppName: path.Base(pkgName), - } + initializeProject(project) - if err := project.Create(); err != nil { - er(err) - } + fmt.Fprintln(cmd.OutOrStdout(), `Your Cobra application is ready at +`+project.AbsPath()+` - fmt.Printf("Your Cobra applicaton is ready at\n%s\n", project.AbsolutePath) - }, +Give it a try by going there and running `+"`go run main.go`."+` +Add commands to it by running `+"`cobra add [cmdname]`.") + }, +} + +func initializeProject(project *Project) { + if !exists(project.AbsPath()) { // If path doesn't yet exist, create it + err := os.MkdirAll(project.AbsPath(), os.ModePerm) + if err != nil { + er(err) + } + } else if !isEmpty(project.AbsPath()) { // If path exists and is not empty don't use it + er("Cobra will not create a new project in a non empty directory: " + project.AbsPath()) + } + + // We have a directory and it's empty. Time to initialize it. + createLicenseFile(project.License(), project.AbsPath()) + createMainFile(project) + createRootCmdFile(project) +} + +func createLicenseFile(license License, path string) { + data := make(map[string]interface{}) + data["copyright"] = copyrightLine() + + // Generate license template from text and data. + text, err := executeTemplate(license.Text, data) + if err != nil { + er(err) + } + + // Write license text to LICENSE file. + err = writeStringToFile(filepath.Join(path, "LICENSE"), text) + if err != nil { + er(err) + } +} + +func createMainFile(project *Project) { + mainTemplate := `{{ comment .copyright }} +{{if .license}}{{ comment .license }}{{end}} + +package main + +import "{{ .importpath }}" + +func main() { + cmd.Execute() +} +` + data := make(map[string]interface{}) + data["copyright"] = copyrightLine() + data["license"] = project.License().Header + data["importpath"] = path.Join(project.Name(), filepath.Base(project.CmdPath())) + + mainScript, err := executeTemplate(mainTemplate, data) + if err != nil { + er(err) + } + + err = writeStringToFile(filepath.Join(project.AbsPath(), "main.go"), mainScript) + if err != nil { + er(err) + } +} + +func createRootCmdFile(project *Project) { + template := `{{comment .copyright}} +{{if .license}}{{comment .license}}{{end}} + +package cmd + +import ( + "fmt" + "os" +{{if .viper}} + homedir "github.com/mitchellh/go-homedir"{{end}} + "github.com/spf13/cobra"{{if .viper}} + "github.com/spf13/viper"{{end}} +){{if .viper}} + +var cfgFile string{{end}} + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "{{.appName}}", + Short: "A brief description of your application", + Long: ` + "`" + `A longer description that spans multiple lines and likely contains +examples and usage of using your application. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.` + "`" + `, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } +} + +func init() { {{- if .viper}} + cobra.OnInitialize(initConfig) +{{end}} + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application.{{ if .viper }} + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ else }} + // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.{{ .appName }}.yaml)"){{ end }} + + // Cobra also supports local flags, which will only run + // when this action is called directly. + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +}{{ if .viper }} + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".{{ .appName }}" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".{{ .appName }}") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } +}{{ end }} +` + + data := make(map[string]interface{}) + data["copyright"] = copyrightLine() + data["viper"] = viper.GetBool("useViper") + data["license"] = project.License().Header + data["appName"] = path.Base(project.Name()) + + rootCmdScript, err := executeTemplate(template, data) + if err != nil { + er(err) + } + + err = writeStringToFile(filepath.Join(project.CmdPath(), "root.go"), rootCmdScript) + if err != nil { + er(err) } -) -func init() { - initCmd.Flags().StringVar(&pkgName, "pkg-name", "", "fully qualified pkg name") - initCmd.MarkFlagRequired("pkg-name") } diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/init_test.go b/vendor/github.com/spf13/cobra/cobra/cmd/init_test.go index 8ee3910612..40eb4038e4 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/init_test.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/init_test.go @@ -1,39 +1,83 @@ package cmd import ( - "fmt" + "errors" + "io/ioutil" "os" "path/filepath" "testing" -) -func getProject() *Project { - wd, _ := os.Getwd() - return &Project{ - AbsolutePath: fmt.Sprintf("%s/testproject", wd), - Legal: getLicense(), - Copyright: copyrightLine(), - AppName: "testproject", - PkgName: "github.com/spf13/testproject", - Viper: true, - } -} + "github.com/spf13/viper" +) +// TestGoldenInitCmd initializes the project "github.com/spf13/testproject" +// in GOPATH and compares the content of files in initialized project with +// appropriate golden files ("testdata/*.golden"). +// Use -update to update existing golden files. func TestGoldenInitCmd(t *testing.T) { - project := getProject() - defer os.RemoveAll(project.AbsolutePath) + projectName := "github.com/spf13/testproject" + project := NewProject(projectName) + defer os.RemoveAll(project.AbsPath()) - if err := project.Create(); err != nil { - t.Fatal(err) + viper.Set("author", "NAME HERE ") + viper.Set("license", "apache") + viper.Set("year", 2017) + defer viper.Set("author", nil) + defer viper.Set("license", nil) + defer viper.Set("year", nil) + + os.Args = []string{"cobra", "init", projectName} + if err := rootCmd.Execute(); err != nil { + t.Fatal("Error by execution:", err) } - expectedFiles := []string{"LICENSE", "main.go", "cmd/root.go"} - for _, f := range expectedFiles { - generatedFile := fmt.Sprintf("%s/%s", project.AbsolutePath, f) - goldenFile := fmt.Sprintf("testdata/%s.golden", filepath.Base(f)) - err := compareFiles(generatedFile, goldenFile) + expectedFiles := []string{".", "cmd", "LICENSE", "main.go", "cmd/root.go"} + gotFiles := []string{} + + // Check project file hierarchy and compare the content of every single file + // with appropriate golden file. + err := filepath.Walk(project.AbsPath(), func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + // Make path relative to project.AbsPath(). + // E.g. path = "/home/user/go/src/github.com/spf13/testproject/cmd/root.go" + // then it returns just "cmd/root.go". + relPath, err := filepath.Rel(project.AbsPath(), path) if err != nil { - t.Fatal(err) + return err + } + relPath = filepath.ToSlash(relPath) + gotFiles = append(gotFiles, relPath) + goldenPath := filepath.Join("testdata", filepath.Base(path)+".golden") + + switch relPath { + // Known directories. + case ".", "cmd": + return nil + // Known files. + case "LICENSE", "main.go", "cmd/root.go": + if *update { + got, err := ioutil.ReadFile(path) + if err != nil { + return err + } + if err := ioutil.WriteFile(goldenPath, got, 0644); err != nil { + t.Fatal("Error while updating file:", err) + } + } + return compareFiles(path, goldenPath) } + // Unknown file. + return errors.New("unknown file: " + path) + }) + if err != nil { + t.Fatal(err) + } + + // Check if some files lack. + if err := checkLackFiles(expectedFiles, gotFiles); err != nil { + t.Fatal(err) } } diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/project.go b/vendor/github.com/spf13/cobra/cobra/cmd/project.go index ecd783d030..7ddb825857 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/project.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/project.go @@ -1,97 +1,200 @@ package cmd import ( - "fmt" "os" - "text/template" - - "github.com/spf13/cobra/cobra/tpl" + "path/filepath" + "runtime" + "strings" ) // Project contains name, license and paths to projects. type Project struct { - // v2 - PkgName string - Copyright string - AbsolutePath string - Legal License - Viper bool - AppName string + absPath string + cmdPath string + srcPath string + license License + name string } -type Command struct { - CmdName string - CmdParent string - *Project -} +// NewProject returns Project with specified project name. +func NewProject(projectName string) *Project { + if projectName == "" { + er("can't create project with blank name") + } + + p := new(Project) + p.name = projectName -func (p *Project) Create() error { - // check if AbsolutePath exists - if _, err := os.Stat(p.AbsolutePath); os.IsNotExist(err) { - // create directory - if err := os.Mkdir(p.AbsolutePath, 0754); err != nil { - return err + // 1. Find already created protect. + p.absPath = findPackage(projectName) + + // 2. If there are no created project with this path, and user is in GOPATH, + // then use GOPATH/src/projectName. + if p.absPath == "" { + wd, err := os.Getwd() + if err != nil { + er(err) + } + for _, srcPath := range srcPaths { + goPath := filepath.Dir(srcPath) + if filepathHasPrefix(wd, goPath) { + p.absPath = filepath.Join(srcPath, projectName) + break + } } } - // create main.go - mainFile, err := os.Create(fmt.Sprintf("%s/main.go", p.AbsolutePath)) - if err != nil { - return err + // 3. If user is not in GOPATH, then use (first GOPATH)/src/projectName. + if p.absPath == "" { + p.absPath = filepath.Join(srcPaths[0], projectName) } - defer mainFile.Close() - mainTemplate := template.Must(template.New("main").Parse(string(tpl.MainTemplate()))) - err = mainTemplate.Execute(mainFile, p) - if err != nil { - return err + return p +} + +// findPackage returns full path to existing go package in GOPATHs. +func findPackage(packageName string) string { + if packageName == "" { + return "" } - // create cmd/root.go - if _, err = os.Stat(fmt.Sprintf("%s/cmd", p.AbsolutePath)); os.IsNotExist(err) { - os.Mkdir(fmt.Sprintf("%s/cmd", p.AbsolutePath), 0751) + for _, srcPath := range srcPaths { + packagePath := filepath.Join(srcPath, packageName) + if exists(packagePath) { + return packagePath + } } - rootFile, err := os.Create(fmt.Sprintf("%s/cmd/root.go", p.AbsolutePath)) + + return "" +} + +// NewProjectFromPath returns Project with specified absolute path to +// package. +func NewProjectFromPath(absPath string) *Project { + if absPath == "" { + er("can't create project: absPath can't be blank") + } + if !filepath.IsAbs(absPath) { + er("can't create project: absPath is not absolute") + } + + // If absPath is symlink, use its destination. + fi, err := os.Lstat(absPath) if err != nil { - return err + er("can't read path info: " + err.Error()) + } + if fi.Mode()&os.ModeSymlink != 0 { + path, err := os.Readlink(absPath) + if err != nil { + er("can't read the destination of symlink: " + err.Error()) + } + absPath = path } - defer rootFile.Close() - rootTemplate := template.Must(template.New("root").Parse(string(tpl.RootTemplate()))) - err = rootTemplate.Execute(rootFile, p) + p := new(Project) + p.absPath = strings.TrimSuffix(absPath, findCmdDir(absPath)) + p.name = filepath.ToSlash(trimSrcPath(p.absPath, p.SrcPath())) + return p +} + +// trimSrcPath trims at the beginning of absPath the srcPath. +func trimSrcPath(absPath, srcPath string) string { + relPath, err := filepath.Rel(srcPath, absPath) if err != nil { - return err + er(err) + } + return relPath +} + +// License returns the License object of project. +func (p *Project) License() License { + if p.license.Text == "" && p.license.Name != "None" { + p.license = getLicense() } + return p.license +} - // create license - return p.createLicenseFile() +// Name returns the name of project, e.g. "github.com/spf13/cobra" +func (p Project) Name() string { + return p.name } -func (p *Project) createLicenseFile() error { - data := map[string]interface{}{ - "copyright": copyrightLine(), +// CmdPath returns absolute path to directory, where all commands are located. +func (p *Project) CmdPath() string { + if p.absPath == "" { + return "" } - licenseFile, err := os.Create(fmt.Sprintf("%s/LICENSE", p.AbsolutePath)) - if err != nil { - return err + if p.cmdPath == "" { + p.cmdPath = filepath.Join(p.absPath, findCmdDir(p.absPath)) + } + return p.cmdPath +} + +// findCmdDir checks if base of absPath is cmd dir and returns it or +// looks for existing cmd dir in absPath. +func findCmdDir(absPath string) string { + if !exists(absPath) || isEmpty(absPath) { + return "cmd" } - defer licenseFile.Close() - licenseTemplate := template.Must(template.New("license").Parse(p.Legal.Text)) - return licenseTemplate.Execute(licenseFile, data) + if isCmdDir(absPath) { + return filepath.Base(absPath) + } + + files, _ := filepath.Glob(filepath.Join(absPath, "c*")) + for _, file := range files { + if isCmdDir(file) { + return filepath.Base(file) + } + } + + return "cmd" } -func (c *Command) Create() error { - cmdFile, err := os.Create(fmt.Sprintf("%s/cmd/%s.go", c.AbsolutePath, c.CmdName)) - if err != nil { - return err +// isCmdDir checks if base of name is one of cmdDir. +func isCmdDir(name string) bool { + name = filepath.Base(name) + for _, cmdDir := range []string{"cmd", "cmds", "command", "commands"} { + if name == cmdDir { + return true + } } - defer cmdFile.Close() + return false +} - commandTemplate := template.Must(template.New("sub").Parse(string(tpl.AddCommandTemplate()))) - err = commandTemplate.Execute(cmdFile, c) - if err != nil { - return err +// AbsPath returns absolute path of project. +func (p Project) AbsPath() string { + return p.absPath +} + +// SrcPath returns absolute path to $GOPATH/src where project is located. +func (p *Project) SrcPath() string { + if p.srcPath != "" { + return p.srcPath + } + if p.absPath == "" { + p.srcPath = srcPaths[0] + return p.srcPath + } + + for _, srcPath := range srcPaths { + if filepathHasPrefix(p.absPath, srcPath) { + p.srcPath = srcPath + break + } } - return nil + + return p.srcPath +} + +func filepathHasPrefix(path string, prefix string) bool { + if len(path) <= len(prefix) { + return false + } + if runtime.GOOS == "windows" { + // Paths in windows are case-insensitive. + return strings.EqualFold(path[0:len(prefix)], prefix) + } + return path[0:len(prefix)] == prefix + } diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/project_test.go b/vendor/github.com/spf13/cobra/cobra/cmd/project_test.go index ed5b054a29..037f7c554e 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/project_test.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/project_test.go @@ -1,3 +1,24 @@ package cmd -/* todo: write tests */ +import ( + "testing" +) + +func TestFindExistingPackage(t *testing.T) { + path := findPackage("github.com/spf13/cobra") + if path == "" { + t.Fatal("findPackage didn't find the existing package") + } + if !hasGoPathPrefix(path) { + t.Fatalf("%q is not in GOPATH, but must be", path) + } +} + +func hasGoPathPrefix(path string) bool { + for _, srcPath := range srcPaths { + if filepathHasPrefix(path, srcPath) { + return true + } + } + return false +} diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/root.go b/vendor/github.com/spf13/cobra/cobra/cmd/root.go index 97f404bbb6..19568f9802 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/root.go +++ b/vendor/github.com/spf13/cobra/cobra/cmd/root.go @@ -23,8 +23,7 @@ import ( var ( // Used for flags. - cfgFile string - userLicense string + cfgFile, userLicense string rootCmd = &cobra.Command{ Use: "cobra", @@ -36,8 +35,8 @@ to quickly create a Cobra application.`, ) // Execute executes the root command. -func Execute() error { - return rootCmd.Execute() +func Execute() { + rootCmd.Execute() } func init() { diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/main.go.golden b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/main.go.golden index 4ad570c543..cdbe38d70b 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/main.go.golden +++ b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/main.go.golden @@ -1,22 +1,21 @@ -/* -Copyright © 2019 NAME HERE +// Copyright © 2017 NAME HERE +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ package main import "github.com/spf13/testproject/cmd" func main() { - cmd.Execute() + cmd.Execute() } diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden index d3b889baa6..d74f4cd450 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden +++ b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/root.go.golden @@ -1,97 +1,89 @@ -/* -Copyright © 2019 NAME HERE +// Copyright © 2017 NAME HERE +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ package cmd import ( - "fmt" - "os" - "github.com/spf13/cobra" - - homedir "github.com/mitchellh/go-homedir" - "github.com/spf13/viper" + "fmt" + "os" + homedir "github.com/mitchellh/go-homedir" + "github.com/spf13/cobra" + "github.com/spf13/viper" ) - var cfgFile string - // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ - Use: "testproject", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains + Use: "testproject", + Short: "A brief description of your application", + Long: `A longer description that spans multiple lines and likely contains examples and usage of using your application. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) { }, } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { - if err := rootCmd.Execute(); err != nil { - fmt.Println(err) - os.Exit(1) - } + if err := rootCmd.Execute(); err != nil { + fmt.Println(err) + os.Exit(1) + } } func init() { - cobra.OnInitialize(initConfig) - - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. + cobra.OnInitialize(initConfig) - rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.testproject.yaml)") + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.testproject.yaml)") - - // Cobra also supports local flags, which will only run - // when this action is called directly. - rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") + // Cobra also supports local flags, which will only run + // when this action is called directly. + rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } - // initConfig reads in config file and ENV variables if set. func initConfig() { - if cfgFile != "" { - // Use config file from the flag. - viper.SetConfigFile(cfgFile) - } else { - // Find home directory. - home, err := homedir.Dir() - if err != nil { - fmt.Println(err) - os.Exit(1) - } - - // Search config in home directory with name ".testproject" (without extension). - viper.AddConfigPath(home) - viper.SetConfigName(".testproject") - } - - viper.AutomaticEnv() // read in environment variables that match - - // If a config file is found, read it in. - if err := viper.ReadInConfig(); err == nil { - fmt.Println("Using config file:", viper.ConfigFileUsed()) - } + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := homedir.Dir() + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Search config in home directory with name ".testproject" (without extension). + viper.AddConfigPath(home) + viper.SetConfigName(".testproject") + } + + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Println("Using config file:", viper.ConfigFileUsed()) + } } - diff --git a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden index fb8e0fa90d..ed64427554 100644 --- a/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden +++ b/vendor/github.com/spf13/cobra/cobra/cmd/testdata/test.go.golden @@ -1,18 +1,17 @@ -/* -Copyright © 2019 NAME HERE +// Copyright © 2017 NAME HERE +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ package cmd import ( diff --git a/vendor/github.com/spf13/cobra/cobra/main.go b/vendor/github.com/spf13/cobra/cobra/main.go index eeaf9824ef..c3a9d9cb04 100644 --- a/vendor/github.com/spf13/cobra/cobra/main.go +++ b/vendor/github.com/spf13/cobra/cobra/main.go @@ -13,14 +13,8 @@ package main -import ( - "os" - - "github.com/spf13/cobra/cobra/cmd" -) +import "github.com/spf13/cobra/cobra/cmd" func main() { - if err := cmd.Execute(); err != nil { - os.Exit(1) - } + cmd.Execute() } diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 42e500de58..b257f91b6f 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -17,7 +17,6 @@ package cobra import ( "bytes" - "errors" "fmt" "io" "os" @@ -28,8 +27,6 @@ import ( flag "github.com/spf13/pflag" ) -var ErrSubCommandRequired = errors.New("subcommand is required") - // FParseErrWhitelist configures Flag parse errors to be ignored type FParseErrWhitelist flag.ParseErrorsWhitelist @@ -180,6 +177,8 @@ type Command struct { // that we can use on every pflag set and children commands globNormFunc func(f *flag.FlagSet, name string) flag.NormalizedName + // output is an output writer defined by user. + output io.Writer // usageFunc is usage func defined by user. usageFunc func(*Command) error // usageTemplate is usage template defined by user. @@ -196,13 +195,6 @@ type Command struct { helpCommand *Command // versionTemplate is the version template defined by user. versionTemplate string - - // inReader is a reader defined by the user that replaces stdin - inReader io.Reader - // outWriter is a writer defined by the user that replaces stdout - outWriter io.Writer - // errWriter is a writer defined by the user that replaces stderr - errWriter io.Writer } // SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden @@ -213,28 +205,8 @@ func (c *Command) SetArgs(a []string) { // SetOutput sets the destination for usage and error messages. // If output is nil, os.Stderr is used. -// Deprecated: Use SetOut and/or SetErr instead func (c *Command) SetOutput(output io.Writer) { - c.outWriter = output - c.errWriter = output -} - -// SetOut sets the destination for usage messages. -// If newOut is nil, os.Stdout is used. -func (c *Command) SetOut(newOut io.Writer) { - c.outWriter = newOut -} - -// SetErr sets the destination for error messages. -// If newErr is nil, os.Stderr is used. -func (c *Command) SetErr(newErr io.Writer) { - c.errWriter = newErr -} - -// SetIn sets the source for input data -// If newIn is nil, os.Stdin is used. -func (c *Command) SetIn(newIn io.Reader) { - c.inReader = newIn + c.output = output } // SetUsageFunc sets usage function. Usage can be defined by application. @@ -295,19 +267,9 @@ func (c *Command) OutOrStderr() io.Writer { return c.getOut(os.Stderr) } -// ErrOrStderr returns output to stderr -func (c *Command) ErrOrStderr() io.Writer { - return c.getErr(os.Stderr) -} - -// InOrStdin returns output to stderr -func (c *Command) InOrStdin() io.Reader { - return c.getIn(os.Stdin) -} - func (c *Command) getOut(def io.Writer) io.Writer { - if c.outWriter != nil { - return c.outWriter + if c.output != nil { + return c.output } if c.HasParent() { return c.parent.getOut(def) @@ -315,26 +277,6 @@ func (c *Command) getOut(def io.Writer) io.Writer { return def } -func (c *Command) getErr(def io.Writer) io.Writer { - if c.errWriter != nil { - return c.errWriter - } - if c.HasParent() { - return c.parent.getErr(def) - } - return def -} - -func (c *Command) getIn(def io.Reader) io.Reader { - if c.inReader != nil { - return c.inReader - } - if c.HasParent() { - return c.parent.getIn(def) - } - return def -} - // UsageFunc returns either the function set by SetUsageFunc for this command // or a parent, or it returns a default usage function. func (c *Command) UsageFunc() (f func(*Command) error) { @@ -372,7 +314,7 @@ func (c *Command) HelpFunc() func(*Command, []string) { } return func(c *Command, a []string) { c.mergePersistentFlags() - err := tmpl(c.OutOrStderr(), c.HelpTemplate(), c) + err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c) if err != nil { c.Println(err) } @@ -387,22 +329,13 @@ func (c *Command) Help() error { return nil } -// UsageString returns usage string. +// UsageString return usage string. func (c *Command) UsageString() string { - // Storing normal writers - tmpOutput := c.outWriter - tmpErr := c.errWriter - + tmpOutput := c.output bb := new(bytes.Buffer) - c.outWriter = bb - c.errWriter = bb - + c.SetOutput(bb) c.Usage() - - // Setting things back to normal - c.outWriter = tmpOutput - c.errWriter = tmpErr - + c.output = tmpOutput return bb.String() } @@ -789,7 +722,7 @@ func (c *Command) execute(a []string) (err error) { } if !c.Runnable() { - return ErrSubCommandRequired + return flag.ErrHelp } c.preRun() @@ -923,14 +856,6 @@ func (c *Command) ExecuteC() (cmd *Command, err error) { return cmd, nil } - // If command wasn't runnable, show full help, but do return the error. - // This will result in apps by default returning a non-success exit code, but also gives them the option to - // handle specially. - if err == ErrSubCommandRequired { - cmd.HelpFunc()(cmd, args) - return cmd, err - } - // If root command has SilentErrors flagged, // all subcommands should respect it if !cmd.SilenceErrors && !c.SilenceErrors { @@ -1143,21 +1068,6 @@ func (c *Command) Printf(format string, i ...interface{}) { c.Print(fmt.Sprintf(format, i...)) } -// PrintErr is a convenience method to Print to the defined Err output, fallback to Stderr if not set. -func (c *Command) PrintErr(i ...interface{}) { - fmt.Fprint(c.ErrOrStderr(), i...) -} - -// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set. -func (c *Command) PrintErrln(i ...interface{}) { - c.Print(fmt.Sprintln(i...)) -} - -// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set. -func (c *Command) PrintErrf(format string, i ...interface{}) { - c.Print(fmt.Sprintf(format, i...)) -} - // CommandPath returns the full path to this command. func (c *Command) CommandPath() string { if c.HasParent() { diff --git a/vendor/github.com/spf13/cobra/command_test.go b/vendor/github.com/spf13/cobra/command_test.go index b26bd4abeb..6e483a3ec4 100644 --- a/vendor/github.com/spf13/cobra/command_test.go +++ b/vendor/github.com/spf13/cobra/command_test.go @@ -836,8 +836,8 @@ func TestHelpExecutedOnNonRunnableChild(t *testing.T) { rootCmd.AddCommand(childCmd) output, err := executeCommand(rootCmd, "child") - if err != ErrSubCommandRequired { - t.Errorf("Expected error") + if err != nil { + t.Errorf("Unexpected error: %v", err) } checkStringContains(t, output, childCmd.Long) @@ -1381,46 +1381,6 @@ func TestSetOutput(t *testing.T) { } } -func TestSetOut(t *testing.T) { - c := &Command{} - c.SetOut(nil) - if out := c.OutOrStdout(); out != os.Stdout { - t.Errorf("Expected setting output to nil to revert back to stdout") - } -} - -func TestSetErr(t *testing.T) { - c := &Command{} - c.SetErr(nil) - if out := c.ErrOrStderr(); out != os.Stderr { - t.Errorf("Expected setting error to nil to revert back to stderr") - } -} - -func TestSetIn(t *testing.T) { - c := &Command{} - c.SetIn(nil) - if out := c.InOrStdin(); out != os.Stdin { - t.Errorf("Expected setting input to nil to revert back to stdin") - } -} - -func TestUsageStringRedirected(t *testing.T) { - c := &Command{} - - c.usageFunc = func(cmd *Command) error { - cmd.Print("[stdout1]") - cmd.PrintErr("[stderr2]") - cmd.Print("[stdout3]") - return nil - } - - expected := "[stdout1][stderr2][stdout3]" - if got := c.UsageString(); got != expected { - t.Errorf("Expected usage string to consider both stdout and stderr") - } -} - func TestFlagErrorFunc(t *testing.T) { c := &Command{Use: "c", Run: emptyRun} diff --git a/vendor/github.com/spf13/cobra/powershell_completions.go b/vendor/github.com/spf13/cobra/powershell_completions.go deleted file mode 100644 index 756c61b9dc..0000000000 --- a/vendor/github.com/spf13/cobra/powershell_completions.go +++ /dev/null @@ -1,100 +0,0 @@ -// PowerShell completions are based on the amazing work from clap: -// https://github.com/clap-rs/clap/blob/3294d18efe5f264d12c9035f404c7d189d4824e1/src/completions/powershell.rs -// -// The generated scripts require PowerShell v5.0+ (which comes Windows 10, but -// can be downloaded separately for windows 7 or 8.1). - -package cobra - -import ( - "bytes" - "fmt" - "io" - "os" - "strings" - - "github.com/spf13/pflag" -) - -var powerShellCompletionTemplate = `using namespace System.Management.Automation -using namespace System.Management.Automation.Language -Register-ArgumentCompleter -Native -CommandName '%s' -ScriptBlock { - param($wordToComplete, $commandAst, $cursorPosition) - $commandElements = $commandAst.CommandElements - $command = @( - '%s' - for ($i = 1; $i -lt $commandElements.Count; $i++) { - $element = $commandElements[$i] - if ($element -isnot [StringConstantExpressionAst] -or - $element.StringConstantType -ne [StringConstantType]::BareWord -or - $element.Value.StartsWith('-')) { - break - } - $element.Value - } - ) -join ';' - $completions = @(switch ($command) {%s - }) - $completions.Where{ $_.CompletionText -like "$wordToComplete*" } | - Sort-Object -Property ListItemText -}` - -func generatePowerShellSubcommandCases(out io.Writer, cmd *Command, previousCommandName string) { - var cmdName string - if previousCommandName == "" { - cmdName = cmd.Name() - } else { - cmdName = fmt.Sprintf("%s;%s", previousCommandName, cmd.Name()) - } - - fmt.Fprintf(out, "\n '%s' {", cmdName) - - cmd.Flags().VisitAll(func(flag *pflag.Flag) { - if nonCompletableFlag(flag) { - return - } - usage := escapeStringForPowerShell(flag.Usage) - if len(flag.Shorthand) > 0 { - fmt.Fprintf(out, "\n [CompletionResult]::new('-%s', '%s', [CompletionResultType]::ParameterName, '%s')", flag.Shorthand, flag.Shorthand, usage) - } - fmt.Fprintf(out, "\n [CompletionResult]::new('--%s', '%s', [CompletionResultType]::ParameterName, '%s')", flag.Name, flag.Name, usage) - }) - - for _, subCmd := range cmd.Commands() { - usage := escapeStringForPowerShell(subCmd.Short) - fmt.Fprintf(out, "\n [CompletionResult]::new('%s', '%s', [CompletionResultType]::ParameterValue, '%s')", subCmd.Name(), subCmd.Name(), usage) - } - - fmt.Fprint(out, "\n break\n }") - - for _, subCmd := range cmd.Commands() { - generatePowerShellSubcommandCases(out, subCmd, cmdName) - } -} - -func escapeStringForPowerShell(s string) string { - return strings.Replace(s, "'", "''", -1) -} - -// GenPowerShellCompletion generates PowerShell completion file and writes to the passed writer. -func (c *Command) GenPowerShellCompletion(w io.Writer) error { - buf := new(bytes.Buffer) - - var subCommandCases bytes.Buffer - generatePowerShellSubcommandCases(&subCommandCases, c, "") - fmt.Fprintf(buf, powerShellCompletionTemplate, c.Name(), c.Name(), subCommandCases.String()) - - _, err := buf.WriteTo(w) - return err -} - -// GenPowerShellCompletionFile generates PowerShell completion file. -func (c *Command) GenPowerShellCompletionFile(filename string) error { - outFile, err := os.Create(filename) - if err != nil { - return err - } - defer outFile.Close() - - return c.GenPowerShellCompletion(outFile) -} diff --git a/vendor/github.com/spf13/cobra/powershell_completions.md b/vendor/github.com/spf13/cobra/powershell_completions.md deleted file mode 100644 index afed802408..0000000000 --- a/vendor/github.com/spf13/cobra/powershell_completions.md +++ /dev/null @@ -1,14 +0,0 @@ -# Generating PowerShell Completions For Your Own cobra.Command - -Cobra can generate PowerShell completion scripts. Users need PowerShell version 5.0 or above, which comes with Windows 10 and can be downloaded separately for Windows 7 or 8.1. They can then write the completions to a file and source this file from their PowerShell profile, which is referenced by the `$Profile` environment variable. See `Get-Help about_Profiles` for more info about PowerShell profiles. - -# What's supported - -- Completion for subcommands using their `.Short` description -- Completion for non-hidden flags using their `.Name` and `.Shorthand` - -# What's not yet supported - -- Command aliases -- Required, filename or custom flags (they will work like normal flags) -- Custom completion scripts diff --git a/vendor/github.com/spf13/cobra/powershell_completions_test.go b/vendor/github.com/spf13/cobra/powershell_completions_test.go deleted file mode 100644 index 29b609de05..0000000000 --- a/vendor/github.com/spf13/cobra/powershell_completions_test.go +++ /dev/null @@ -1,122 +0,0 @@ -package cobra - -import ( - "bytes" - "strings" - "testing" -) - -func TestPowerShellCompletion(t *testing.T) { - tcs := []struct { - name string - root *Command - expectedExpressions []string - }{ - { - name: "trivial", - root: &Command{Use: "trivialapp"}, - expectedExpressions: []string{ - "Register-ArgumentCompleter -Native -CommandName 'trivialapp' -ScriptBlock", - "$command = @(\n 'trivialapp'\n", - }, - }, - { - name: "tree", - root: func() *Command { - r := &Command{Use: "tree"} - - sub1 := &Command{Use: "sub1"} - r.AddCommand(sub1) - - sub11 := &Command{Use: "sub11"} - sub12 := &Command{Use: "sub12"} - - sub1.AddCommand(sub11) - sub1.AddCommand(sub12) - - sub2 := &Command{Use: "sub2"} - r.AddCommand(sub2) - - sub21 := &Command{Use: "sub21"} - sub22 := &Command{Use: "sub22"} - - sub2.AddCommand(sub21) - sub2.AddCommand(sub22) - - return r - }(), - expectedExpressions: []string{ - "'tree'", - "[CompletionResult]::new('sub1', 'sub1', [CompletionResultType]::ParameterValue, '')", - "[CompletionResult]::new('sub2', 'sub2', [CompletionResultType]::ParameterValue, '')", - "'tree;sub1'", - "[CompletionResult]::new('sub11', 'sub11', [CompletionResultType]::ParameterValue, '')", - "[CompletionResult]::new('sub12', 'sub12', [CompletionResultType]::ParameterValue, '')", - "'tree;sub1;sub11'", - "'tree;sub1;sub12'", - "'tree;sub2'", - "[CompletionResult]::new('sub21', 'sub21', [CompletionResultType]::ParameterValue, '')", - "[CompletionResult]::new('sub22', 'sub22', [CompletionResultType]::ParameterValue, '')", - "'tree;sub2;sub21'", - "'tree;sub2;sub22'", - }, - }, - { - name: "flags", - root: func() *Command { - r := &Command{Use: "flags"} - r.Flags().StringP("flag1", "a", "", "") - r.Flags().String("flag2", "", "") - - sub1 := &Command{Use: "sub1"} - sub1.Flags().StringP("flag3", "c", "", "") - r.AddCommand(sub1) - - return r - }(), - expectedExpressions: []string{ - "'flags'", - "[CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, '')", - "[CompletionResult]::new('--flag1', 'flag1', [CompletionResultType]::ParameterName, '')", - "[CompletionResult]::new('--flag2', 'flag2', [CompletionResultType]::ParameterName, '')", - "[CompletionResult]::new('sub1', 'sub1', [CompletionResultType]::ParameterValue, '')", - "'flags;sub1'", - "[CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, '')", - "[CompletionResult]::new('--flag3', 'flag3', [CompletionResultType]::ParameterName, '')", - }, - }, - { - name: "usage", - root: func() *Command { - r := &Command{Use: "usage"} - r.Flags().String("flag", "", "this describes the usage of the 'flag' flag") - - sub1 := &Command{ - Use: "sub1", - Short: "short describes 'sub1'", - } - r.AddCommand(sub1) - - return r - }(), - expectedExpressions: []string{ - "[CompletionResult]::new('--flag', 'flag', [CompletionResultType]::ParameterName, 'this describes the usage of the ''flag'' flag')", - "[CompletionResult]::new('sub1', 'sub1', [CompletionResultType]::ParameterValue, 'short describes ''sub1''')", - }, - }, - } - - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - buf := new(bytes.Buffer) - tc.root.GenPowerShellCompletion(buf) - output := buf.String() - - for _, expectedExpression := range tc.expectedExpressions { - if !strings.Contains(output, expectedExpression) { - t.Errorf("Expected completion to contain %q somewhere; got %q", expectedExpression, output) - } - } - }) - } -} diff --git a/vendor/github.com/spf13/cobra/shell_completions.go b/vendor/github.com/spf13/cobra/shell_completions.go deleted file mode 100644 index ba0af9cb55..0000000000 --- a/vendor/github.com/spf13/cobra/shell_completions.go +++ /dev/null @@ -1,85 +0,0 @@ -package cobra - -import ( - "github.com/spf13/pflag" -) - -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, -// and causes your command to report an error if invoked without the flag. -func (c *Command) MarkFlagRequired(name string) error { - return MarkFlagRequired(c.Flags(), name) -} - -// MarkPersistentFlagRequired adds the BashCompOneRequiredFlag annotation to the named persistent flag if it exists, -// and causes your command to report an error if invoked without the flag. -func (c *Command) MarkPersistentFlagRequired(name string) error { - return MarkFlagRequired(c.PersistentFlags(), name) -} - -// MarkFlagRequired adds the BashCompOneRequiredFlag annotation to the named flag if it exists, -// and causes your command to report an error if invoked without the flag. -func MarkFlagRequired(flags *pflag.FlagSet, name string) error { - return flags.SetAnnotation(name, BashCompOneRequiredFlag, []string{"true"}) -} - -// MarkFlagFilename adds the BashCompFilenameExt annotation to the named flag, if it exists. -// Generated bash autocompletion will select filenames for the flag, limiting to named extensions if provided. -func (c *Command) MarkFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(c.Flags(), name, extensions...) -} - -// MarkFlagCustom adds the BashCompCustom annotation to the named flag, if it exists. -// Generated bash autocompletion will call the bash function f for the flag. -func (c *Command) MarkFlagCustom(name string, f string) error { - return MarkFlagCustom(c.Flags(), name, f) -} - -// MarkPersistentFlagFilename instructs the various shell completion -// implementations to limit completions for this persistent flag to the -// specified extensions (patterns). -// -// Shell Completion compatibility matrix: bash, zsh -func (c *Command) MarkPersistentFlagFilename(name string, extensions ...string) error { - return MarkFlagFilename(c.PersistentFlags(), name, extensions...) -} - -// MarkFlagFilename instructs the various shell completion implementations to -// limit completions for this flag to the specified extensions (patterns). -// -// Shell Completion compatibility matrix: bash, zsh -func MarkFlagFilename(flags *pflag.FlagSet, name string, extensions ...string) error { - return flags.SetAnnotation(name, BashCompFilenameExt, extensions) -} - -// MarkFlagCustom instructs the various shell completion implementations to -// limit completions for this flag to the specified extensions (patterns). -// -// Shell Completion compatibility matrix: bash, zsh -func MarkFlagCustom(flags *pflag.FlagSet, name string, f string) error { - return flags.SetAnnotation(name, BashCompCustom, []string{f}) -} - -// MarkFlagDirname instructs the various shell completion implementations to -// complete only directories with this named flag. -// -// Shell Completion compatibility matrix: zsh -func (c *Command) MarkFlagDirname(name string) error { - return MarkFlagDirname(c.Flags(), name) -} - -// MarkPersistentFlagDirname instructs the various shell completion -// implementations to complete only directories with this persistent named flag. -// -// Shell Completion compatibility matrix: zsh -func (c *Command) MarkPersistentFlagDirname(name string) error { - return MarkFlagDirname(c.PersistentFlags(), name) -} - -// MarkFlagDirname instructs the various shell completion implementations to -// complete only directories with this specified flag. -// -// Shell Completion compatibility matrix: zsh -func MarkFlagDirname(flags *pflag.FlagSet, name string) error { - zshPattern := "-(/)" - return flags.SetAnnotation(name, zshCompDirname, []string{zshPattern}) -} diff --git a/vendor/github.com/spf13/cobra/zsh_completions.go b/vendor/github.com/spf13/cobra/zsh_completions.go index 12755482f0..889c22e273 100644 --- a/vendor/github.com/spf13/cobra/zsh_completions.go +++ b/vendor/github.com/spf13/cobra/zsh_completions.go @@ -1,102 +1,13 @@ package cobra import ( - "encoding/json" + "bytes" "fmt" "io" "os" - "sort" "strings" - "text/template" - - "github.com/spf13/pflag" -) - -const ( - zshCompArgumentAnnotation = "cobra_annotations_zsh_completion_argument_annotation" - zshCompArgumentFilenameComp = "cobra_annotations_zsh_completion_argument_file_completion" - zshCompArgumentWordComp = "cobra_annotations_zsh_completion_argument_word_completion" - zshCompDirname = "cobra_annotations_zsh_dirname" -) - -var ( - zshCompFuncMap = template.FuncMap{ - "genZshFuncName": zshCompGenFuncName, - "extractFlags": zshCompExtractFlag, - "genFlagEntryForZshArguments": zshCompGenFlagEntryForArguments, - "extractArgsCompletions": zshCompExtractArgumentCompletionHintsForRendering, - } - zshCompletionText = ` -{{/* should accept Command (that contains subcommands) as parameter */}} -{{define "argumentsC" -}} -{{ $cmdPath := genZshFuncName .}} -function {{$cmdPath}} { - local -a commands - - _arguments -C \{{- range extractFlags .}} - {{genFlagEntryForZshArguments .}} \{{- end}} - "1: :->cmnds" \ - "*::arg:->args" - - case $state in - cmnds) - commands=({{range .Commands}}{{if not .Hidden}} - "{{.Name}}:{{.Short}}"{{end}}{{end}} - ) - _describe "command" commands - ;; - esac - - case "$words[1]" in {{- range .Commands}}{{if not .Hidden}} - {{.Name}}) - {{$cmdPath}}_{{.Name}} - ;;{{end}}{{end}} - esac -} -{{range .Commands}}{{if not .Hidden}} -{{template "selectCmdTemplate" .}} -{{- end}}{{end}} -{{- end}} - -{{/* should accept Command without subcommands as parameter */}} -{{define "arguments" -}} -function {{genZshFuncName .}} { -{{" _arguments"}}{{range extractFlags .}} \ - {{genFlagEntryForZshArguments . -}} -{{end}}{{range extractArgsCompletions .}} \ - {{.}}{{end}} -} -{{end}} - -{{/* dispatcher for commands with or without subcommands */}} -{{define "selectCmdTemplate" -}} -{{if .Hidden}}{{/* ignore hidden*/}}{{else -}} -{{if .Commands}}{{template "argumentsC" .}}{{else}}{{template "arguments" .}}{{end}} -{{- end}} -{{- end}} - -{{/* template entry point */}} -{{define "Main" -}} -#compdef _{{.Name}} {{.Name}} - -{{template "selectCmdTemplate" .}} -{{end}} -` ) -// zshCompArgsAnnotation is used to encode/decode zsh completion for -// arguments to/from Command.Annotations. -type zshCompArgsAnnotation map[int]zshCompArgHint - -type zshCompArgHint struct { - // Indicates the type of the completion to use. One of: - // zshCompArgumentFilenameComp or zshCompArgumentWordComp - Tipe string `json:"type"` - - // A value for the type above (globs for file completion or words) - Options []string `json:"options"` -} - // GenZshCompletionFile generates zsh completion file. func (c *Command) GenZshCompletionFile(filename string) error { outFile, err := os.Create(filename) @@ -108,229 +19,108 @@ func (c *Command) GenZshCompletionFile(filename string) error { return c.GenZshCompletion(outFile) } -// GenZshCompletion generates a zsh completion file and writes to the passed -// writer. The completion always run on the root command regardless of the -// command it was called from. +// GenZshCompletion generates a zsh completion file and writes to the passed writer. func (c *Command) GenZshCompletion(w io.Writer) error { - tmpl, err := template.New("Main").Funcs(zshCompFuncMap).Parse(zshCompletionText) - if err != nil { - return fmt.Errorf("error creating zsh completion template: %v", err) - } - return tmpl.Execute(w, c.Root()) -} - -// MarkZshCompPositionalArgumentFile marks the specified argument (first -// argument is 1) as completed by file selection. patterns (e.g. "*.txt") are -// optional - if not provided the completion will search for all files. -func (c *Command) MarkZshCompPositionalArgumentFile(argPosition int, patterns ...string) error { - if argPosition < 1 { - return fmt.Errorf("Invalid argument position (%d)", argPosition) - } - annotation, err := c.zshCompGetArgsAnnotations() - if err != nil { - return err - } - if c.zshcompArgsAnnotationnIsDuplicatePosition(annotation, argPosition) { - return fmt.Errorf("Duplicate annotation for positional argument at index %d", argPosition) - } - annotation[argPosition] = zshCompArgHint{ - Tipe: zshCompArgumentFilenameComp, - Options: patterns, - } - return c.zshCompSetArgsAnnotations(annotation) -} - -// MarkZshCompPositionalArgumentWords marks the specified positional argument -// (first argument is 1) as completed by the provided words. At east one word -// must be provided, spaces within words will be offered completion with -// "word\ word". -func (c *Command) MarkZshCompPositionalArgumentWords(argPosition int, words ...string) error { - if argPosition < 1 { - return fmt.Errorf("Invalid argument position (%d)", argPosition) - } - if len(words) == 0 { - return fmt.Errorf("Trying to set empty word list for positional argument %d", argPosition) - } - annotation, err := c.zshCompGetArgsAnnotations() - if err != nil { - return err - } - if c.zshcompArgsAnnotationnIsDuplicatePosition(annotation, argPosition) { - return fmt.Errorf("Duplicate annotation for positional argument at index %d", argPosition) - } - annotation[argPosition] = zshCompArgHint{ - Tipe: zshCompArgumentWordComp, - Options: words, - } - return c.zshCompSetArgsAnnotations(annotation) -} + buf := new(bytes.Buffer) -func zshCompExtractArgumentCompletionHintsForRendering(c *Command) ([]string, error) { - var result []string - annotation, err := c.zshCompGetArgsAnnotations() - if err != nil { - return nil, err - } - for k, v := range annotation { - s, err := zshCompRenderZshCompArgHint(k, v) - if err != nil { - return nil, err - } - result = append(result, s) - } - if len(c.ValidArgs) > 0 { - if _, positionOneExists := annotation[1]; !positionOneExists { - s, err := zshCompRenderZshCompArgHint(1, zshCompArgHint{ - Tipe: zshCompArgumentWordComp, - Options: c.ValidArgs, - }) - if err != nil { - return nil, err - } - result = append(result, s) - } - } - sort.Strings(result) - return result, nil -} + writeHeader(buf, c) + maxDepth := maxDepth(c) + writeLevelMapping(buf, maxDepth) + writeLevelCases(buf, maxDepth, c) -func zshCompRenderZshCompArgHint(i int, z zshCompArgHint) (string, error) { - switch t := z.Tipe; t { - case zshCompArgumentFilenameComp: - var globs []string - for _, g := range z.Options { - globs = append(globs, fmt.Sprintf(`-g "%s"`, g)) - } - return fmt.Sprintf(`'%d: :_files %s'`, i, strings.Join(globs, " ")), nil - case zshCompArgumentWordComp: - var words []string - for _, w := range z.Options { - words = append(words, fmt.Sprintf("%q", w)) - } - return fmt.Sprintf(`'%d: :(%s)'`, i, strings.Join(words, " ")), nil - default: - return "", fmt.Errorf("Invalid zsh argument completion annotation: %s", t) - } + _, err := buf.WriteTo(w) + return err } -func (c *Command) zshcompArgsAnnotationnIsDuplicatePosition(annotation zshCompArgsAnnotation, position int) bool { - _, dup := annotation[position] - return dup +func writeHeader(w io.Writer, cmd *Command) { + fmt.Fprintf(w, "#compdef %s\n\n", cmd.Name()) } -func (c *Command) zshCompGetArgsAnnotations() (zshCompArgsAnnotation, error) { - annotation := make(zshCompArgsAnnotation) - annotationString, ok := c.Annotations[zshCompArgumentAnnotation] - if !ok { - return annotation, nil +func maxDepth(c *Command) int { + if len(c.Commands()) == 0 { + return 0 } - err := json.Unmarshal([]byte(annotationString), &annotation) - if err != nil { - return annotation, fmt.Errorf("Error unmarshaling zsh argument annotation: %v", err) - } - return annotation, nil -} - -func (c *Command) zshCompSetArgsAnnotations(annotation zshCompArgsAnnotation) error { - jsn, err := json.Marshal(annotation) - if err != nil { - return fmt.Errorf("Error marshaling zsh argument annotation: %v", err) - } - if c.Annotations == nil { - c.Annotations = make(map[string]string) + maxDepthSub := 0 + for _, s := range c.Commands() { + subDepth := maxDepth(s) + if subDepth > maxDepthSub { + maxDepthSub = subDepth + } } - c.Annotations[zshCompArgumentAnnotation] = string(jsn) - return nil + return 1 + maxDepthSub } -func zshCompGenFuncName(c *Command) string { - if c.HasParent() { - return zshCompGenFuncName(c.Parent()) + "_" + c.Name() +func writeLevelMapping(w io.Writer, numLevels int) { + fmt.Fprintln(w, `_arguments \`) + for i := 1; i <= numLevels; i++ { + fmt.Fprintf(w, ` '%d: :->level%d' \`, i, i) + fmt.Fprintln(w) } - return "_" + c.Name() + fmt.Fprintf(w, ` '%d: :%s'`, numLevels+1, "_files") + fmt.Fprintln(w) } -func zshCompExtractFlag(c *Command) []*pflag.Flag { - var flags []*pflag.Flag - c.LocalFlags().VisitAll(func(f *pflag.Flag) { - if !f.Hidden { - flags = append(flags, f) - } - }) - c.InheritedFlags().VisitAll(func(f *pflag.Flag) { - if !f.Hidden { - flags = append(flags, f) - } - }) - return flags -} +func writeLevelCases(w io.Writer, maxDepth int, root *Command) { + fmt.Fprintln(w, "case $state in") + defer fmt.Fprintln(w, "esac") -// zshCompGenFlagEntryForArguments returns an entry that matches _arguments -// zsh-completion parameters. It's too complicated to generate in a template. -func zshCompGenFlagEntryForArguments(f *pflag.Flag) string { - if f.Name == "" || f.Shorthand == "" { - return zshCompGenFlagEntryForSingleOptionFlag(f) + for i := 1; i <= maxDepth; i++ { + fmt.Fprintf(w, " level%d)\n", i) + writeLevel(w, root, i) + fmt.Fprintln(w, " ;;") } - return zshCompGenFlagEntryForMultiOptionFlag(f) + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") } -func zshCompGenFlagEntryForSingleOptionFlag(f *pflag.Flag) string { - var option, multiMark, extras string +func writeLevel(w io.Writer, root *Command, i int) { + fmt.Fprintf(w, " case $words[%d] in\n", i) + defer fmt.Fprintln(w, " esac") - if zshCompFlagCouldBeSpecifiedMoreThenOnce(f) { - multiMark = "*" - } + commands := filterByLevel(root, i) + byParent := groupByParent(commands) - option = "--" + f.Name - if option == "--" { - option = "-" + f.Shorthand + for p, c := range byParent { + names := names(c) + fmt.Fprintf(w, " %s)\n", p) + fmt.Fprintf(w, " _arguments '%d: :(%s)'\n", i, strings.Join(names, " ")) + fmt.Fprintln(w, " ;;") } - extras = zshCompGenFlagEntryExtras(f) + fmt.Fprintln(w, " *)") + fmt.Fprintln(w, " _arguments '*: :_files'") + fmt.Fprintln(w, " ;;") - return fmt.Sprintf(`'%s%s[%s]%s'`, multiMark, option, zshCompQuoteFlagDescription(f.Usage), extras) } -func zshCompGenFlagEntryForMultiOptionFlag(f *pflag.Flag) string { - var options, parenMultiMark, curlyMultiMark, extras string - - if zshCompFlagCouldBeSpecifiedMoreThenOnce(f) { - parenMultiMark = "*" - curlyMultiMark = "\\*" +func filterByLevel(c *Command, l int) []*Command { + cs := make([]*Command, 0) + if l == 0 { + cs = append(cs, c) + return cs } - - options = fmt.Sprintf(`'(%s-%s %s--%s)'{%s-%s,%s--%s}`, - parenMultiMark, f.Shorthand, parenMultiMark, f.Name, curlyMultiMark, f.Shorthand, curlyMultiMark, f.Name) - extras = zshCompGenFlagEntryExtras(f) - - return fmt.Sprintf(`%s'[%s]%s'`, options, zshCompQuoteFlagDescription(f.Usage), extras) -} - -func zshCompGenFlagEntryExtras(f *pflag.Flag) string { - if f.NoOptDefVal != "" { - return "" + for _, s := range c.Commands() { + cs = append(cs, filterByLevel(s, l-1)...) } + return cs +} - extras := ":" // allow options for flag (even without assistance) - for key, values := range f.Annotations { - switch key { - case zshCompDirname: - extras = fmt.Sprintf(":filename:_files -g %q", values[0]) - case BashCompFilenameExt: - extras = ":filename:_files" - for _, pattern := range values { - extras = extras + fmt.Sprintf(` -g "%s"`, pattern) - } +func groupByParent(commands []*Command) map[string][]*Command { + m := make(map[string][]*Command) + for _, c := range commands { + parent := c.Parent() + if parent == nil { + continue } + m[parent.Name()] = append(m[parent.Name()], c) } - - return extras -} - -func zshCompFlagCouldBeSpecifiedMoreThenOnce(f *pflag.Flag) bool { - return strings.Contains(f.Value.Type(), "Slice") || - strings.Contains(f.Value.Type(), "Array") + return m } -func zshCompQuoteFlagDescription(s string) string { - return strings.Replace(s, "'", `'\''`, -1) +func names(commands []*Command) []string { + ns := make([]string, len(commands)) + for i, c := range commands { + ns[i] = c.Name() + } + return ns } diff --git a/vendor/github.com/spf13/cobra/zsh_completions.md b/vendor/github.com/spf13/cobra/zsh_completions.md deleted file mode 100644 index df9c2eac93..0000000000 --- a/vendor/github.com/spf13/cobra/zsh_completions.md +++ /dev/null @@ -1,39 +0,0 @@ -## Generating Zsh Completion for your cobra.Command - -Cobra supports native Zsh completion generated from the root `cobra.Command`. -The generated completion script should be put somewhere in your `$fpath` named -`_`. - -### What's Supported - -* Completion for all non-hidden subcommands using their `.Short` description. -* Completion for all non-hidden flags using the following rules: - * Filename completion works by marking the flag with `cmd.MarkFlagFilename...` - family of commands. - * The requirement for argument to the flag is decided by the `.NoOptDefVal` - flag value - if it's empty then completion will expect an argument. - * Flags of one of the various `*Array` and `*Slice` types supports multiple - specifications (with or without argument depending on the specific type). -* Completion of positional arguments using the following rules: - * Argument position for all options below starts at `1`. If argument position - `0` is requested it will raise an error. - * Use `command.MarkZshCompPositionalArgumentFile` to complete filenames. Glob - patterns (e.g. `"*.log"`) are optional - if not specified it will offer to - complete all file types. - * Use `command.MarkZshCompPositionalArgumentWords` to offer specific words for - completion. At least one word is required. - * It's possible to specify completion for some arguments and leave some - unspecified (e.g. offer words for second argument but nothing for first - argument). This will cause no completion for first argument but words - completion for second argument. - * If no argument completion was specified for 1st argument (but optionally was - specified for 2nd) and the command has `ValidArgs` it will be used as - completion options for 1st argument. - * Argument completions only offered for commands with no subcommands. - -### What's not yet Supported - -* Custom completion scripts are not supported yet (We should probably create zsh - specific one, doesn't make sense to re-use the bash one as the functions will - be different). -* Whatever other feature you're looking for and doesn't exist :) diff --git a/vendor/github.com/spf13/cobra/zsh_completions_test.go b/vendor/github.com/spf13/cobra/zsh_completions_test.go index e53fa886e5..34e69496f2 100644 --- a/vendor/github.com/spf13/cobra/zsh_completions_test.go +++ b/vendor/github.com/spf13/cobra/zsh_completions_test.go @@ -2,474 +2,88 @@ package cobra import ( "bytes" - "regexp" "strings" "testing" ) -func TestGenZshCompletion(t *testing.T) { - var debug bool - var option string - +func TestZshCompletion(t *testing.T) { tcs := []struct { name string root *Command expectedExpressions []string - invocationArgs []string - skip string }{ { - name: "simple command", - root: func() *Command { - r := &Command{ - Use: "mycommand", - Long: "My Command long description", - Run: emptyRun, - } - r.Flags().BoolVar(&debug, "debug", debug, "description") - return r - }(), - expectedExpressions: []string{ - `(?s)function _mycommand {\s+_arguments \\\s+'--debug\[description\]'.*--help.*}`, - "#compdef _mycommand mycommand", - }, - }, - { - name: "flags with both long and short flags", - root: func() *Command { - r := &Command{ - Use: "testcmd", - Long: "long description", - Run: emptyRun, - } - r.Flags().BoolVarP(&debug, "debug", "d", debug, "debug description") - return r - }(), - expectedExpressions: []string{ - `'\(-d --debug\)'{-d,--debug}'\[debug description\]'`, - }, - }, - { - name: "command with subcommands and flags with values", - root: func() *Command { - r := &Command{ - Use: "rootcmd", - Long: "Long rootcmd description", - } - d := &Command{ - Use: "subcmd1", - Short: "Subcmd1 short description", - Run: emptyRun, - } - e := &Command{ - Use: "subcmd2", - Long: "Subcmd2 short description", - Run: emptyRun, - } - r.PersistentFlags().BoolVar(&debug, "debug", debug, "description") - d.Flags().StringVarP(&option, "option", "o", option, "option description") - r.AddCommand(d, e) - return r - }(), - expectedExpressions: []string{ - `commands=\(\n\s+"help:.*\n\s+"subcmd1:.*\n\s+"subcmd2:.*\n\s+\)`, - `_arguments \\\n.*'--debug\[description]'`, - `_arguments -C \\\n.*'--debug\[description]'`, - `function _rootcmd_subcmd1 {`, - `function _rootcmd_subcmd1 {`, - `_arguments \\\n.*'\(-o --option\)'{-o,--option}'\[option description]:' \\\n`, - }, - }, - { - name: "filename completion with and without globs", - root: func() *Command { - var file string - r := &Command{ - Use: "mycmd", - Short: "my command short description", - Run: emptyRun, - } - r.Flags().StringVarP(&file, "config", "c", file, "config file") - r.MarkFlagFilename("config") - r.Flags().String("output", "", "output file") - r.MarkFlagFilename("output", "*.log", "*.txt") - return r - }(), - expectedExpressions: []string{ - `\n +'\(-c --config\)'{-c,--config}'\[config file]:filename:_files'`, - `:_files -g "\*.log" -g "\*.txt"`, - }, - }, - { - name: "repeated variables both with and without value", - root: func() *Command { - r := genTestCommand("mycmd", true) - _ = r.Flags().BoolSliceP("debug", "d", []bool{}, "debug usage") - _ = r.Flags().StringArray("option", []string{}, "options") - return r - }(), - expectedExpressions: []string{ - `'\*--option\[options]`, - `'\(\*-d \*--debug\)'{\\\*-d,\\\*--debug}`, - }, - }, - { - name: "generated flags --help and --version should be created even when not executing root cmd", - root: func() *Command { - r := &Command{ - Use: "mycmd", - Short: "mycmd short description", - Version: "myversion", - } - s := genTestCommand("sub1", true) - r.AddCommand(s) - return s - }(), - expectedExpressions: []string{ - "--version", - "--help", - }, - invocationArgs: []string{ - "sub1", - }, - skip: "--version and --help are currently not generated when not running on root command", - }, - { - name: "zsh generation should run on root command", - root: func() *Command { - r := genTestCommand("root", false) - s := genTestCommand("sub1", true) - r.AddCommand(s) - return s - }(), - expectedExpressions: []string{ - "function _root {", - }, - }, - { - name: "flag description with single quote (') shouldn't break quotes in completion file", - root: func() *Command { - r := genTestCommand("root", true) - r.Flags().Bool("private", false, "Don't show public info") - return r - }(), - expectedExpressions: []string{ - `--private\[Don'\\''t show public info]`, - }, - }, - { - name: "argument completion for file with and without patterns", - root: func() *Command { - r := genTestCommand("root", true) - r.MarkZshCompPositionalArgumentFile(1, "*.log") - r.MarkZshCompPositionalArgumentFile(2) - return r - }(), - expectedExpressions: []string{ - `'1: :_files -g "\*.log"' \\\n\s+'2: :_files`, - }, - }, - { - name: "argument zsh completion for words", - root: func() *Command { - r := genTestCommand("root", true) - r.MarkZshCompPositionalArgumentWords(1, "word1", "word2") - return r - }(), - expectedExpressions: []string{ - `'1: :\("word1" "word2"\)`, - }, - }, - { - name: "argument completion for words with spaces", - root: func() *Command { - r := genTestCommand("root", true) - r.MarkZshCompPositionalArgumentWords(1, "single", "multiple words") - return r - }(), - expectedExpressions: []string{ - `'1: :\("single" "multiple words"\)'`, - }, + name: "trivial", + root: &Command{Use: "trivialapp"}, + expectedExpressions: []string{"#compdef trivial"}, }, { - name: "argument completion when command has ValidArgs and no annotation for argument completion", + name: "linear", root: func() *Command { - r := genTestCommand("root", true) - r.ValidArgs = []string{"word1", "word2"} + r := &Command{Use: "linear"} + + sub1 := &Command{Use: "sub1"} + r.AddCommand(sub1) + + sub2 := &Command{Use: "sub2"} + sub1.AddCommand(sub2) + + sub3 := &Command{Use: "sub3"} + sub2.AddCommand(sub3) return r }(), - expectedExpressions: []string{ - `'1: :\("word1" "word2"\)'`, - }, + expectedExpressions: []string{"sub1", "sub2", "sub3"}, }, { - name: "argument completion when command has ValidArgs and no annotation for argument at argPosition 1", + name: "flat", root: func() *Command { - r := genTestCommand("root", true) - r.ValidArgs = []string{"word1", "word2"} - r.MarkZshCompPositionalArgumentFile(2) + r := &Command{Use: "flat"} + r.AddCommand(&Command{Use: "c1"}) + r.AddCommand(&Command{Use: "c2"}) return r }(), - expectedExpressions: []string{ - `'1: :\("word1" "word2"\)' \\`, - }, + expectedExpressions: []string{"(c1 c2)"}, }, { - name: "directory completion for flag", + name: "tree", root: func() *Command { - r := genTestCommand("root", true) - r.Flags().String("test", "", "test") - r.PersistentFlags().String("ptest", "", "ptest") - r.MarkFlagDirname("test") - r.MarkPersistentFlagDirname("ptest") - return r - }(), - expectedExpressions: []string{ - `--test\[test]:filename:_files -g "-\(/\)"`, - `--ptest\[ptest]:filename:_files -g "-\(/\)"`, - }, - }, - } + r := &Command{Use: "tree"} - for _, tc := range tcs { - t.Run(tc.name, func(t *testing.T) { - if tc.skip != "" { - t.Skip(tc.skip) - } - tc.root.Root().SetArgs(tc.invocationArgs) - tc.root.Execute() - buf := new(bytes.Buffer) - if err := tc.root.GenZshCompletion(buf); err != nil { - t.Error(err) - } - output := buf.Bytes() + sub1 := &Command{Use: "sub1"} + r.AddCommand(sub1) - for _, expr := range tc.expectedExpressions { - rgx, err := regexp.Compile(expr) - if err != nil { - t.Errorf("error compiling expression (%s): %v", expr, err) - } - if !rgx.Match(output) { - t.Errorf("expected completion (%s) to match '%s'", buf.String(), expr) - } - } - }) - } -} + sub11 := &Command{Use: "sub11"} + sub12 := &Command{Use: "sub12"} -func TestGenZshCompletionHidden(t *testing.T) { - tcs := []struct { - name string - root *Command - expectedExpressions []string - }{ - { - name: "hidden commands", - root: func() *Command { - r := &Command{ - Use: "main", - Short: "main short description", - } - s1 := &Command{ - Use: "sub1", - Hidden: true, - Run: emptyRun, - } - s2 := &Command{ - Use: "sub2", - Short: "short sub2 description", - Run: emptyRun, - } - r.AddCommand(s1, s2) + sub1.AddCommand(sub11) + sub1.AddCommand(sub12) + + sub2 := &Command{Use: "sub2"} + r.AddCommand(sub2) + + sub21 := &Command{Use: "sub21"} + sub22 := &Command{Use: "sub22"} + + sub2.AddCommand(sub21) + sub2.AddCommand(sub22) return r }(), - expectedExpressions: []string{ - "sub1", - }, - }, - { - name: "hidden flags", - root: func() *Command { - var hidden string - r := &Command{ - Use: "root", - Short: "root short description", - Run: emptyRun, - } - r.Flags().StringVarP(&hidden, "hidden", "H", hidden, "hidden usage") - if err := r.Flags().MarkHidden("hidden"); err != nil { - t.Errorf("Error setting flag hidden: %v\n", err) - } - return r - }(), - expectedExpressions: []string{ - "--hidden", - }, + expectedExpressions: []string{"(sub11 sub12)", "(sub21 sub22)"}, }, } for _, tc := range tcs { t.Run(tc.name, func(t *testing.T) { - tc.root.Execute() buf := new(bytes.Buffer) - if err := tc.root.GenZshCompletion(buf); err != nil { - t.Error(err) - } + tc.root.GenZshCompletion(buf) output := buf.String() - for _, expr := range tc.expectedExpressions { - if strings.Contains(output, expr) { - t.Errorf("Expected completion (%s) not to contain '%s' but it does", output, expr) + for _, expectedExpression := range tc.expectedExpressions { + if !strings.Contains(output, expectedExpression) { + t.Errorf("Expected completion to contain %q somewhere; got %q", expectedExpression, output) } } }) } } - -func TestMarkZshCompPositionalArgumentFile(t *testing.T) { - t.Run("Doesn't allow overwriting existing positional argument", func(t *testing.T) { - c := &Command{} - if err := c.MarkZshCompPositionalArgumentFile(1, "*.log"); err != nil { - t.Errorf("Received error when we shouldn't have: %v\n", err) - } - if err := c.MarkZshCompPositionalArgumentFile(1); err == nil { - t.Error("Didn't receive an error when trying to overwrite argument position") - } - }) - - t.Run("Refuses to accept argPosition less then 1", func(t *testing.T) { - c := &Command{} - err := c.MarkZshCompPositionalArgumentFile(0, "*") - if err == nil { - t.Fatal("Error was not thrown when indicating argument position 0") - } - if !strings.Contains(err.Error(), "position") { - t.Errorf("expected error message '%s' to contain 'position'", err.Error()) - } - }) -} - -func TestMarkZshCompPositionalArgumentWords(t *testing.T) { - t.Run("Doesn't allow overwriting existing positional argument", func(t *testing.T) { - c := &Command{} - if err := c.MarkZshCompPositionalArgumentFile(1, "*.log"); err != nil { - t.Errorf("Received error when we shouldn't have: %v\n", err) - } - if err := c.MarkZshCompPositionalArgumentWords(1, "hello"); err == nil { - t.Error("Didn't receive an error when trying to overwrite argument position") - } - }) - - t.Run("Doesn't allow calling without words", func(t *testing.T) { - c := &Command{} - if err := c.MarkZshCompPositionalArgumentWords(0); err == nil { - t.Error("Should not allow saving empty word list for annotation") - } - }) - - t.Run("Refuses to accept argPosition less then 1", func(t *testing.T) { - c := &Command{} - err := c.MarkZshCompPositionalArgumentWords(0, "word") - if err == nil { - t.Fatal("Should not allow setting argument position less then 1") - } - if !strings.Contains(err.Error(), "position") { - t.Errorf("Expected error '%s' to contain 'position' but didn't", err.Error()) - } - }) -} - -func BenchmarkMediumSizeConstruct(b *testing.B) { - root := constructLargeCommandHierarchy() - // if err := root.GenZshCompletionFile("_mycmd"); err != nil { - // b.Error(err) - // } - - for i := 0; i < b.N; i++ { - buf := new(bytes.Buffer) - err := root.GenZshCompletion(buf) - if err != nil { - b.Error(err) - } - } -} - -func TestExtractFlags(t *testing.T) { - var debug, cmdc, cmdd bool - c := &Command{ - Use: "cmdC", - Long: "Command C", - } - c.PersistentFlags().BoolVarP(&debug, "debug", "d", debug, "debug mode") - c.Flags().BoolVar(&cmdc, "cmd-c", cmdc, "Command C") - d := &Command{ - Use: "CmdD", - Long: "Command D", - } - d.Flags().BoolVar(&cmdd, "cmd-d", cmdd, "Command D") - c.AddCommand(d) - - resC := zshCompExtractFlag(c) - resD := zshCompExtractFlag(d) - - if len(resC) != 2 { - t.Errorf("expected Command C to return 2 flags, got %d", len(resC)) - } - if len(resD) != 2 { - t.Errorf("expected Command D to return 2 flags, got %d", len(resD)) - } -} - -func constructLargeCommandHierarchy() *Command { - var config, st1, st2 string - var long, debug bool - var in1, in2 int - var verbose []bool - - r := genTestCommand("mycmd", false) - r.PersistentFlags().StringVarP(&config, "config", "c", config, "config usage") - if err := r.MarkPersistentFlagFilename("config", "*"); err != nil { - panic(err) - } - s1 := genTestCommand("sub1", true) - s1.Flags().BoolVar(&long, "long", long, "long description") - s1.Flags().BoolSliceVar(&verbose, "verbose", verbose, "verbose description") - s1.Flags().StringArray("option", []string{}, "various options") - s2 := genTestCommand("sub2", true) - s2.PersistentFlags().BoolVar(&debug, "debug", debug, "debug description") - s3 := genTestCommand("sub3", true) - s3.Hidden = true - s1_1 := genTestCommand("sub1sub1", true) - s1_1.Flags().StringVar(&st1, "st1", st1, "st1 description") - s1_1.Flags().StringVar(&st2, "st2", st2, "st2 description") - s1_2 := genTestCommand("sub1sub2", true) - s1_3 := genTestCommand("sub1sub3", true) - s1_3.Flags().IntVar(&in1, "int1", in1, "int1 description") - s1_3.Flags().IntVar(&in2, "int2", in2, "int2 description") - s1_3.Flags().StringArrayP("option", "O", []string{}, "more options") - s2_1 := genTestCommand("sub2sub1", true) - s2_2 := genTestCommand("sub2sub2", true) - s2_3 := genTestCommand("sub2sub3", true) - s2_4 := genTestCommand("sub2sub4", true) - s2_5 := genTestCommand("sub2sub5", true) - - s1.AddCommand(s1_1, s1_2, s1_3) - s2.AddCommand(s2_1, s2_2, s2_3, s2_4, s2_5) - r.AddCommand(s1, s2, s3) - r.Execute() - return r -} - -func genTestCommand(name string, withRun bool) *Command { - r := &Command{ - Use: name, - Short: name + " short description", - Long: "Long description for " + name, - } - if withRun { - r.Run = emptyRun - } - - return r -} diff --git a/vendor/github.com/spf13/pflag/.travis.yml b/vendor/github.com/spf13/pflag/.travis.yml index 00d04cb9b0..f8a63b308b 100644 --- a/vendor/github.com/spf13/pflag/.travis.yml +++ b/vendor/github.com/spf13/pflag/.travis.yml @@ -3,9 +3,8 @@ sudo: false language: go go: - - 1.9.x - - 1.10.x - - 1.11.x + - 1.7.3 + - 1.8.1 - tip matrix: @@ -13,7 +12,7 @@ matrix: - go: tip install: - - go get golang.org/x/lint/golint + - go get github.com/golang/lint/golint - export PATH=$GOPATH/bin:$PATH - go install ./... diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md index 7eacc5bdbe..b052414d12 100644 --- a/vendor/github.com/spf13/pflag/README.md +++ b/vendor/github.com/spf13/pflag/README.md @@ -86,8 +86,8 @@ fmt.Println("ip has value ", *ip) fmt.Println("flagvar has value ", flagvar) ``` -There are helper functions available to get the value stored in a Flag if you have a FlagSet but find -it difficult to keep up with all of the pointers in your code. +There are helpers function to get values later if you have the FlagSet but +it was difficult to keep up with all of the flag pointers in your code. If you have a pflag.FlagSet with a flag called 'flagname' of type int you can use GetInt() to get the int value. But notice that 'flagname' must exist and it must be an int. GetString("flagname") will fail. diff --git a/vendor/github.com/spf13/pflag/bool_slice.go b/vendor/github.com/spf13/pflag/bool_slice.go index 3731370d6a..5af02f1a75 100644 --- a/vendor/github.com/spf13/pflag/bool_slice.go +++ b/vendor/github.com/spf13/pflag/bool_slice.go @@ -71,44 +71,6 @@ func (s *boolSliceValue) String() string { return "[" + out + "]" } -func (s *boolSliceValue) fromString(val string) (bool, error) { - return strconv.ParseBool(val) -} - -func (s *boolSliceValue) toString(val bool) string { - return strconv.FormatBool(val) -} - -func (s *boolSliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *boolSliceValue) Replace(val []string) error { - out := make([]bool, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *boolSliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - func boolSliceConv(val string) (interface{}, error) { val = strings.Trim(val, "[]") // Empty string would cause a slice with one (empty) entry diff --git a/vendor/github.com/spf13/pflag/bool_slice_test.go b/vendor/github.com/spf13/pflag/bool_slice_test.go index 3c5a274f07..b617dd237f 100644 --- a/vendor/github.com/spf13/pflag/bool_slice_test.go +++ b/vendor/github.com/spf13/pflag/bool_slice_test.go @@ -160,29 +160,6 @@ func TestBSCalledTwice(t *testing.T) { } } -func TestBSAsSliceValue(t *testing.T) { - var bs []bool - f := setUpBSFlagSet(&bs) - - in := []string{"true", "false"} - argfmt := "--bs=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"false"}) - } - }) - if len(bs) != 1 || bs[0] != false { - t.Fatalf("Expected ss to be overwritten with 'false', but got: %v", bs) - } -} - func TestBSBadQuoting(t *testing.T) { tests := []struct { diff --git a/vendor/github.com/spf13/pflag/count.go b/vendor/github.com/spf13/pflag/count.go index a0b2679f71..aa126e44d1 100644 --- a/vendor/github.com/spf13/pflag/count.go +++ b/vendor/github.com/spf13/pflag/count.go @@ -46,7 +46,7 @@ func (f *FlagSet) GetCount(name string) (int, error) { // CountVar defines a count flag with specified name, default value, and usage string. // The argument p points to an int variable in which to store the value of the flag. -// A count flag will add 1 to its value every time it is found on the command line +// A count flag will add 1 to its value evey time it is found on the command line func (f *FlagSet) CountVar(p *int, name string, usage string) { f.CountVarP(p, name, "", usage) } @@ -69,7 +69,7 @@ func CountVarP(p *int, name, shorthand string, usage string) { // Count defines a count flag with specified name, default value, and usage string. // The return value is the address of an int variable that stores the value of the flag. -// A count flag will add 1 to its value every time it is found on the command line +// A count flag will add 1 to its value evey time it is found on the command line func (f *FlagSet) Count(name string, usage string) *int { p := new(int) f.CountVarP(p, name, "", usage) diff --git a/vendor/github.com/spf13/pflag/duration_slice.go b/vendor/github.com/spf13/pflag/duration_slice.go index badadda53f..52c6b6dc10 100644 --- a/vendor/github.com/spf13/pflag/duration_slice.go +++ b/vendor/github.com/spf13/pflag/duration_slice.go @@ -51,44 +51,6 @@ func (s *durationSliceValue) String() string { return "[" + strings.Join(out, ",") + "]" } -func (s *durationSliceValue) fromString(val string) (time.Duration, error) { - return time.ParseDuration(val) -} - -func (s *durationSliceValue) toString(val time.Duration) string { - return fmt.Sprintf("%s", val) -} - -func (s *durationSliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *durationSliceValue) Replace(val []string) error { - out := make([]time.Duration, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *durationSliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - func durationSliceConv(val string) (interface{}, error) { val = strings.Trim(val, "[]") // Empty string would cause a slice with one (empty) entry diff --git a/vendor/github.com/spf13/pflag/duration_slice_test.go b/vendor/github.com/spf13/pflag/duration_slice_test.go index 651fbd8b5b..489b012ffd 100644 --- a/vendor/github.com/spf13/pflag/duration_slice_test.go +++ b/vendor/github.com/spf13/pflag/duration_slice_test.go @@ -144,29 +144,6 @@ func TestDSWithDefault(t *testing.T) { } } -func TestDSAsSliceValue(t *testing.T) { - var ds []time.Duration - f := setUpDSFlagSet(&ds) - - in := []string{"1ns", "2ns"} - argfmt := "--ds=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"3ns"}) - } - }) - if len(ds) != 1 || ds[0] != time.Duration(3) { - t.Fatalf("Expected ss to be overwritten with '3ns', but got: %v", ds) - } -} - func TestDSCalledTwice(t *testing.T) { var ds []time.Duration f := setUpDSFlagSet(&ds) diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index 24a5036e95..9beeda8ecc 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -57,9 +57,9 @@ that give one-letter shorthands for flags. You can use these by appending var ip = flag.IntP("flagname", "f", 1234, "help message") var flagvar bool func init() { - flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") + flag.BoolVarP("boolname", "b", true, "help message") } - flag.VarP(&flagval, "varname", "v", "help message") + flag.VarP(&flagVar, "varname", "v", 1234, "help message") Shorthand letters can be used with single dashes on the command line. Boolean shorthand flags can be combined with other shorthand flags. @@ -190,18 +190,6 @@ type Value interface { Type() string } -// SliceValue is a secondary interface to all flags which hold a list -// of values. This allows full control over the value of list flags, -// and avoids complicated marshalling and unmarshalling to csv. -type SliceValue interface { - // Append adds the specified value to the end of the flag value list. - Append(string) error - // Replace will fully overwrite any data currently in the flag value list. - Replace([]string) error - // GetSlice returns the flag value list as an array of strings. - GetSlice() []string -} - // sortFlags returns the flags as a slice in lexicographical sorted order. func sortFlags(flags map[NormalizedName]*Flag) []*Flag { list := make(sort.StringSlice, len(flags)) diff --git a/vendor/github.com/spf13/pflag/float32_slice.go b/vendor/github.com/spf13/pflag/float32_slice.go deleted file mode 100644 index caa352741a..0000000000 --- a/vendor/github.com/spf13/pflag/float32_slice.go +++ /dev/null @@ -1,174 +0,0 @@ -package pflag - -import ( - "fmt" - "strconv" - "strings" -) - -// -- float32Slice Value -type float32SliceValue struct { - value *[]float32 - changed bool -} - -func newFloat32SliceValue(val []float32, p *[]float32) *float32SliceValue { - isv := new(float32SliceValue) - isv.value = p - *isv.value = val - return isv -} - -func (s *float32SliceValue) Set(val string) error { - ss := strings.Split(val, ",") - out := make([]float32, len(ss)) - for i, d := range ss { - var err error - var temp64 float64 - temp64, err = strconv.ParseFloat(d, 32) - if err != nil { - return err - } - out[i] = float32(temp64) - - } - if !s.changed { - *s.value = out - } else { - *s.value = append(*s.value, out...) - } - s.changed = true - return nil -} - -func (s *float32SliceValue) Type() string { - return "float32Slice" -} - -func (s *float32SliceValue) String() string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = fmt.Sprintf("%f", d) - } - return "[" + strings.Join(out, ",") + "]" -} - -func (s *float32SliceValue) fromString(val string) (float32, error) { - t64, err := strconv.ParseFloat(val, 32) - if err != nil { - return 0, err - } - return float32(t64), nil -} - -func (s *float32SliceValue) toString(val float32) string { - return fmt.Sprintf("%f", val) -} - -func (s *float32SliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *float32SliceValue) Replace(val []string) error { - out := make([]float32, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *float32SliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - -func float32SliceConv(val string) (interface{}, error) { - val = strings.Trim(val, "[]") - // Empty string would cause a slice with one (empty) entry - if len(val) == 0 { - return []float32{}, nil - } - ss := strings.Split(val, ",") - out := make([]float32, len(ss)) - for i, d := range ss { - var err error - var temp64 float64 - temp64, err = strconv.ParseFloat(d, 32) - if err != nil { - return nil, err - } - out[i] = float32(temp64) - - } - return out, nil -} - -// GetFloat32Slice return the []float32 value of a flag with the given name -func (f *FlagSet) GetFloat32Slice(name string) ([]float32, error) { - val, err := f.getFlagType(name, "float32Slice", float32SliceConv) - if err != nil { - return []float32{}, err - } - return val.([]float32), nil -} - -// Float32SliceVar defines a float32Slice flag with specified name, default value, and usage string. -// The argument p points to a []float32 variable in which to store the value of the flag. -func (f *FlagSet) Float32SliceVar(p *[]float32, name string, value []float32, usage string) { - f.VarP(newFloat32SliceValue(value, p), name, "", usage) -} - -// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) { - f.VarP(newFloat32SliceValue(value, p), name, shorthand, usage) -} - -// Float32SliceVar defines a float32[] flag with specified name, default value, and usage string. -// The argument p points to a float32[] variable in which to store the value of the flag. -func Float32SliceVar(p *[]float32, name string, value []float32, usage string) { - CommandLine.VarP(newFloat32SliceValue(value, p), name, "", usage) -} - -// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash. -func Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) { - CommandLine.VarP(newFloat32SliceValue(value, p), name, shorthand, usage) -} - -// Float32Slice defines a []float32 flag with specified name, default value, and usage string. -// The return value is the address of a []float32 variable that stores the value of the flag. -func (f *FlagSet) Float32Slice(name string, value []float32, usage string) *[]float32 { - p := []float32{} - f.Float32SliceVarP(&p, name, "", value, usage) - return &p -} - -// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 { - p := []float32{} - f.Float32SliceVarP(&p, name, shorthand, value, usage) - return &p -} - -// Float32Slice defines a []float32 flag with specified name, default value, and usage string. -// The return value is the address of a []float32 variable that stores the value of the flag. -func Float32Slice(name string, value []float32, usage string) *[]float32 { - return CommandLine.Float32SliceP(name, "", value, usage) -} - -// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash. -func Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 { - return CommandLine.Float32SliceP(name, shorthand, value, usage) -} diff --git a/vendor/github.com/spf13/pflag/float32_slice_test.go b/vendor/github.com/spf13/pflag/float32_slice_test.go deleted file mode 100644 index 997ce5c686..0000000000 --- a/vendor/github.com/spf13/pflag/float32_slice_test.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpF32SFlagSet(f32sp *[]float32) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Float32SliceVar(f32sp, "f32s", []float32{}, "Command separated list!") - return f -} - -func setUpF32SFlagSetWithDefault(f32sp *[]float32) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Float32SliceVar(f32sp, "f32s", []float32{0.0, 1.0}, "Command separated list!") - return f -} - -func TestEmptyF32S(t *testing.T) { - var f32s []float32 - f := setUpF32SFlagSet(&f32s) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getF32S, err := f.GetFloat32Slice("f32s") - if err != nil { - t.Fatal("got an error from GetFloat32Slice():", err) - } - if len(getF32S) != 0 { - t.Fatalf("got f32s %v with len=%d but expected length=0", getF32S, len(getF32S)) - } -} - -func TestF32S(t *testing.T) { - var f32s []float32 - f := setUpF32SFlagSet(&f32s) - - vals := []string{"1.0", "2.0", "4.0", "3.0"} - arg := fmt.Sprintf("--f32s=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f32s { - d64, err := strconv.ParseFloat(vals[i], 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - - d := float32(d64) - if d != v { - t.Fatalf("expected f32s[%d] to be %s but got: %f", i, vals[i], v) - } - } - getF32S, err := f.GetFloat32Slice("f32s") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getF32S { - d64, err := strconv.ParseFloat(vals[i], 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - - d := float32(d64) - if d != v { - t.Fatalf("expected f32s[%d] to be %s but got: %f from GetFloat32Slice", i, vals[i], v) - } - } -} - -func TestF32SDefault(t *testing.T) { - var f32s []float32 - f := setUpF32SFlagSetWithDefault(&f32s) - - vals := []string{"0.0", "1.0"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f32s { - d64, err := strconv.ParseFloat(vals[i], 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - - d := float32(d64) - if d != v { - t.Fatalf("expected f32s[%d] to be %f but got: %f", i, d, v) - } - } - - getF32S, err := f.GetFloat32Slice("f32s") - if err != nil { - t.Fatal("got an error from GetFloat32Slice():", err) - } - for i, v := range getF32S { - d64, err := strconv.ParseFloat(vals[i], 32) - if err != nil { - t.Fatal("got an error from GetFloat32Slice():", err) - } - - d := float32(d64) - if d != v { - t.Fatalf("expected f32s[%d] to be %f from GetFloat32Slice but got: %f", i, d, v) - } - } -} - -func TestF32SWithDefault(t *testing.T) { - var f32s []float32 - f := setUpF32SFlagSetWithDefault(&f32s) - - vals := []string{"1.0", "2.0"} - arg := fmt.Sprintf("--f32s=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f32s { - d64, err := strconv.ParseFloat(vals[i], 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - - d := float32(d64) - if d != v { - t.Fatalf("expected f32s[%d] to be %f but got: %f", i, d, v) - } - } - - getF32S, err := f.GetFloat32Slice("f32s") - if err != nil { - t.Fatal("got an error from GetFloat32Slice():", err) - } - for i, v := range getF32S { - d64, err := strconv.ParseFloat(vals[i], 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - - d := float32(d64) - if d != v { - t.Fatalf("expected f32s[%d] to be %f from GetFloat32Slice but got: %f", i, d, v) - } - } -} - -func TestF32SAsSliceValue(t *testing.T) { - var f32s []float32 - f := setUpF32SFlagSet(&f32s) - - in := []string{"1.0", "2.0"} - argfmt := "--f32s=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"3.1"}) - } - }) - if len(f32s) != 1 || f32s[0] != 3.1 { - t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", f32s) - } -} - -func TestF32SCalledTwice(t *testing.T) { - var f32s []float32 - f := setUpF32SFlagSet(&f32s) - - in := []string{"1.0,2.0", "3.0"} - expected := []float32{1.0, 2.0, 3.0} - argfmt := "--f32s=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f32s { - if expected[i] != v { - t.Fatalf("expected f32s[%d] to be %f but got: %f", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/float64_slice.go b/vendor/github.com/spf13/pflag/float64_slice.go deleted file mode 100644 index 85bf3073d5..0000000000 --- a/vendor/github.com/spf13/pflag/float64_slice.go +++ /dev/null @@ -1,166 +0,0 @@ -package pflag - -import ( - "fmt" - "strconv" - "strings" -) - -// -- float64Slice Value -type float64SliceValue struct { - value *[]float64 - changed bool -} - -func newFloat64SliceValue(val []float64, p *[]float64) *float64SliceValue { - isv := new(float64SliceValue) - isv.value = p - *isv.value = val - return isv -} - -func (s *float64SliceValue) Set(val string) error { - ss := strings.Split(val, ",") - out := make([]float64, len(ss)) - for i, d := range ss { - var err error - out[i], err = strconv.ParseFloat(d, 64) - if err != nil { - return err - } - - } - if !s.changed { - *s.value = out - } else { - *s.value = append(*s.value, out...) - } - s.changed = true - return nil -} - -func (s *float64SliceValue) Type() string { - return "float64Slice" -} - -func (s *float64SliceValue) String() string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = fmt.Sprintf("%f", d) - } - return "[" + strings.Join(out, ",") + "]" -} - -func (s *float64SliceValue) fromString(val string) (float64, error) { - return strconv.ParseFloat(val, 64) -} - -func (s *float64SliceValue) toString(val float64) string { - return fmt.Sprintf("%f", val) -} - -func (s *float64SliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *float64SliceValue) Replace(val []string) error { - out := make([]float64, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *float64SliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - -func float64SliceConv(val string) (interface{}, error) { - val = strings.Trim(val, "[]") - // Empty string would cause a slice with one (empty) entry - if len(val) == 0 { - return []float64{}, nil - } - ss := strings.Split(val, ",") - out := make([]float64, len(ss)) - for i, d := range ss { - var err error - out[i], err = strconv.ParseFloat(d, 64) - if err != nil { - return nil, err - } - - } - return out, nil -} - -// GetFloat64Slice return the []float64 value of a flag with the given name -func (f *FlagSet) GetFloat64Slice(name string) ([]float64, error) { - val, err := f.getFlagType(name, "float64Slice", float64SliceConv) - if err != nil { - return []float64{}, err - } - return val.([]float64), nil -} - -// Float64SliceVar defines a float64Slice flag with specified name, default value, and usage string. -// The argument p points to a []float64 variable in which to store the value of the flag. -func (f *FlagSet) Float64SliceVar(p *[]float64, name string, value []float64, usage string) { - f.VarP(newFloat64SliceValue(value, p), name, "", usage) -} - -// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) { - f.VarP(newFloat64SliceValue(value, p), name, shorthand, usage) -} - -// Float64SliceVar defines a float64[] flag with specified name, default value, and usage string. -// The argument p points to a float64[] variable in which to store the value of the flag. -func Float64SliceVar(p *[]float64, name string, value []float64, usage string) { - CommandLine.VarP(newFloat64SliceValue(value, p), name, "", usage) -} - -// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash. -func Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) { - CommandLine.VarP(newFloat64SliceValue(value, p), name, shorthand, usage) -} - -// Float64Slice defines a []float64 flag with specified name, default value, and usage string. -// The return value is the address of a []float64 variable that stores the value of the flag. -func (f *FlagSet) Float64Slice(name string, value []float64, usage string) *[]float64 { - p := []float64{} - f.Float64SliceVarP(&p, name, "", value, usage) - return &p -} - -// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 { - p := []float64{} - f.Float64SliceVarP(&p, name, shorthand, value, usage) - return &p -} - -// Float64Slice defines a []float64 flag with specified name, default value, and usage string. -// The return value is the address of a []float64 variable that stores the value of the flag. -func Float64Slice(name string, value []float64, usage string) *[]float64 { - return CommandLine.Float64SliceP(name, "", value, usage) -} - -// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash. -func Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 { - return CommandLine.Float64SliceP(name, shorthand, value, usage) -} diff --git a/vendor/github.com/spf13/pflag/float64_slice_test.go b/vendor/github.com/spf13/pflag/float64_slice_test.go deleted file mode 100644 index 43778ef103..0000000000 --- a/vendor/github.com/spf13/pflag/float64_slice_test.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpF64SFlagSet(f64sp *[]float64) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Float64SliceVar(f64sp, "f64s", []float64{}, "Command separated list!") - return f -} - -func setUpF64SFlagSetWithDefault(f64sp *[]float64) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Float64SliceVar(f64sp, "f64s", []float64{0.0, 1.0}, "Command separated list!") - return f -} - -func TestEmptyF64S(t *testing.T) { - var f64s []float64 - f := setUpF64SFlagSet(&f64s) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getF64S, err := f.GetFloat64Slice("f64s") - if err != nil { - t.Fatal("got an error from GetFloat64Slice():", err) - } - if len(getF64S) != 0 { - t.Fatalf("got f64s %v with len=%d but expected length=0", getF64S, len(getF64S)) - } -} - -func TestF64S(t *testing.T) { - var f64s []float64 - f := setUpF64SFlagSet(&f64s) - - vals := []string{"1.0", "2.0", "4.0", "3.0"} - arg := fmt.Sprintf("--f64s=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f64s { - d, err := strconv.ParseFloat(vals[i], 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected f64s[%d] to be %s but got: %f", i, vals[i], v) - } - } - getF64S, err := f.GetFloat64Slice("f64s") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getF64S { - d, err := strconv.ParseFloat(vals[i], 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected f64s[%d] to be %s but got: %f from GetFloat64Slice", i, vals[i], v) - } - } -} - -func TestF64SDefault(t *testing.T) { - var f64s []float64 - f := setUpF64SFlagSetWithDefault(&f64s) - - vals := []string{"0.0", "1.0"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f64s { - d, err := strconv.ParseFloat(vals[i], 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected f64s[%d] to be %f but got: %f", i, d, v) - } - } - - getF64S, err := f.GetFloat64Slice("f64s") - if err != nil { - t.Fatal("got an error from GetFloat64Slice():", err) - } - for i, v := range getF64S { - d, err := strconv.ParseFloat(vals[i], 64) - if err != nil { - t.Fatal("got an error from GetFloat64Slice():", err) - } - if d != v { - t.Fatalf("expected f64s[%d] to be %f from GetFloat64Slice but got: %f", i, d, v) - } - } -} - -func TestF64SWithDefault(t *testing.T) { - var f64s []float64 - f := setUpF64SFlagSetWithDefault(&f64s) - - vals := []string{"1.0", "2.0"} - arg := fmt.Sprintf("--f64s=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f64s { - d, err := strconv.ParseFloat(vals[i], 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected f64s[%d] to be %f but got: %f", i, d, v) - } - } - - getF64S, err := f.GetFloat64Slice("f64s") - if err != nil { - t.Fatal("got an error from GetFloat64Slice():", err) - } - for i, v := range getF64S { - d, err := strconv.ParseFloat(vals[i], 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected f64s[%d] to be %f from GetFloat64Slice but got: %f", i, d, v) - } - } -} - -func TestF64SAsSliceValue(t *testing.T) { - var f64s []float64 - f := setUpF64SFlagSet(&f64s) - - in := []string{"1.0", "2.0"} - argfmt := "--f64s=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"3.1"}) - } - }) - if len(f64s) != 1 || f64s[0] != 3.1 { - t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", f64s) - } -} - -func TestF64SCalledTwice(t *testing.T) { - var f64s []float64 - f := setUpF64SFlagSet(&f64s) - - in := []string{"1.0,2.0", "3.0"} - expected := []float64{1.0, 2.0, 3.0} - argfmt := "--f64s=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range f64s { - if expected[i] != v { - t.Fatalf("expected f64s[%d] to be %f but got: %f", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/go.mod b/vendor/github.com/spf13/pflag/go.mod deleted file mode 100644 index b2287eec13..0000000000 --- a/vendor/github.com/spf13/pflag/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/spf13/pflag - -go 1.12 diff --git a/vendor/github.com/spf13/pflag/go.sum b/vendor/github.com/spf13/pflag/go.sum deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/vendor/github.com/spf13/pflag/int32_slice.go b/vendor/github.com/spf13/pflag/int32_slice.go deleted file mode 100644 index ff128ff06d..0000000000 --- a/vendor/github.com/spf13/pflag/int32_slice.go +++ /dev/null @@ -1,174 +0,0 @@ -package pflag - -import ( - "fmt" - "strconv" - "strings" -) - -// -- int32Slice Value -type int32SliceValue struct { - value *[]int32 - changed bool -} - -func newInt32SliceValue(val []int32, p *[]int32) *int32SliceValue { - isv := new(int32SliceValue) - isv.value = p - *isv.value = val - return isv -} - -func (s *int32SliceValue) Set(val string) error { - ss := strings.Split(val, ",") - out := make([]int32, len(ss)) - for i, d := range ss { - var err error - var temp64 int64 - temp64, err = strconv.ParseInt(d, 0, 32) - if err != nil { - return err - } - out[i] = int32(temp64) - - } - if !s.changed { - *s.value = out - } else { - *s.value = append(*s.value, out...) - } - s.changed = true - return nil -} - -func (s *int32SliceValue) Type() string { - return "int32Slice" -} - -func (s *int32SliceValue) String() string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = fmt.Sprintf("%d", d) - } - return "[" + strings.Join(out, ",") + "]" -} - -func (s *int32SliceValue) fromString(val string) (int32, error) { - t64, err := strconv.ParseInt(val, 0, 32) - if err != nil { - return 0, err - } - return int32(t64), nil -} - -func (s *int32SliceValue) toString(val int32) string { - return fmt.Sprintf("%d", val) -} - -func (s *int32SliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *int32SliceValue) Replace(val []string) error { - out := make([]int32, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *int32SliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - -func int32SliceConv(val string) (interface{}, error) { - val = strings.Trim(val, "[]") - // Empty string would cause a slice with one (empty) entry - if len(val) == 0 { - return []int32{}, nil - } - ss := strings.Split(val, ",") - out := make([]int32, len(ss)) - for i, d := range ss { - var err error - var temp64 int64 - temp64, err = strconv.ParseInt(d, 0, 32) - if err != nil { - return nil, err - } - out[i] = int32(temp64) - - } - return out, nil -} - -// GetInt32Slice return the []int32 value of a flag with the given name -func (f *FlagSet) GetInt32Slice(name string) ([]int32, error) { - val, err := f.getFlagType(name, "int32Slice", int32SliceConv) - if err != nil { - return []int32{}, err - } - return val.([]int32), nil -} - -// Int32SliceVar defines a int32Slice flag with specified name, default value, and usage string. -// The argument p points to a []int32 variable in which to store the value of the flag. -func (f *FlagSet) Int32SliceVar(p *[]int32, name string, value []int32, usage string) { - f.VarP(newInt32SliceValue(value, p), name, "", usage) -} - -// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) { - f.VarP(newInt32SliceValue(value, p), name, shorthand, usage) -} - -// Int32SliceVar defines a int32[] flag with specified name, default value, and usage string. -// The argument p points to a int32[] variable in which to store the value of the flag. -func Int32SliceVar(p *[]int32, name string, value []int32, usage string) { - CommandLine.VarP(newInt32SliceValue(value, p), name, "", usage) -} - -// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash. -func Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) { - CommandLine.VarP(newInt32SliceValue(value, p), name, shorthand, usage) -} - -// Int32Slice defines a []int32 flag with specified name, default value, and usage string. -// The return value is the address of a []int32 variable that stores the value of the flag. -func (f *FlagSet) Int32Slice(name string, value []int32, usage string) *[]int32 { - p := []int32{} - f.Int32SliceVarP(&p, name, "", value, usage) - return &p -} - -// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 { - p := []int32{} - f.Int32SliceVarP(&p, name, shorthand, value, usage) - return &p -} - -// Int32Slice defines a []int32 flag with specified name, default value, and usage string. -// The return value is the address of a []int32 variable that stores the value of the flag. -func Int32Slice(name string, value []int32, usage string) *[]int32 { - return CommandLine.Int32SliceP(name, "", value, usage) -} - -// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash. -func Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 { - return CommandLine.Int32SliceP(name, shorthand, value, usage) -} diff --git a/vendor/github.com/spf13/pflag/int32_slice_test.go b/vendor/github.com/spf13/pflag/int32_slice_test.go deleted file mode 100644 index 809c5633aa..0000000000 --- a/vendor/github.com/spf13/pflag/int32_slice_test.go +++ /dev/null @@ -1,194 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpI32SFlagSet(isp *[]int32) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Int32SliceVar(isp, "is", []int32{}, "Command separated list!") - return f -} - -func setUpI32SFlagSetWithDefault(isp *[]int32) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Int32SliceVar(isp, "is", []int32{0, 1}, "Command separated list!") - return f -} - -func TestEmptyI32S(t *testing.T) { - var is []int32 - f := setUpI32SFlagSet(&is) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getI32S, err := f.GetInt32Slice("is") - if err != nil { - t.Fatal("got an error from GetInt32Slice():", err) - } - if len(getI32S) != 0 { - t.Fatalf("got is %v with len=%d but expected length=0", getI32S, len(getI32S)) - } -} - -func TestI32S(t *testing.T) { - var is []int32 - f := setUpI32SFlagSet(&is) - - vals := []string{"1", "2", "4", "3"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d64, err := strconv.ParseInt(vals[i], 0, 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - d := int32(d64) - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d", i, vals[i], v) - } - } - getI32S, err := f.GetInt32Slice("is") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getI32S { - d64, err := strconv.ParseInt(vals[i], 0, 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - d := int32(d64) - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d from GetInt32Slice", i, vals[i], v) - } - } -} - -func TestI32SDefault(t *testing.T) { - var is []int32 - f := setUpI32SFlagSetWithDefault(&is) - - vals := []string{"0", "1"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d64, err := strconv.ParseInt(vals[i], 0, 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - d := int32(d64) - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getI32S, err := f.GetInt32Slice("is") - if err != nil { - t.Fatal("got an error from GetInt32Slice():", err) - } - for i, v := range getI32S { - d64, err := strconv.ParseInt(vals[i], 0, 32) - if err != nil { - t.Fatal("got an error from GetInt32Slice():", err) - } - d := int32(d64) - if d != v { - t.Fatalf("expected is[%d] to be %d from GetInt32Slice but got: %d", i, d, v) - } - } -} - -func TestI32SWithDefault(t *testing.T) { - var is []int32 - f := setUpI32SFlagSetWithDefault(&is) - - vals := []string{"1", "2"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d64, err := strconv.ParseInt(vals[i], 0, 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - d := int32(d64) - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getI32S, err := f.GetInt32Slice("is") - if err != nil { - t.Fatal("got an error from GetInt32Slice():", err) - } - for i, v := range getI32S { - d64, err := strconv.ParseInt(vals[i], 0, 32) - if err != nil { - t.Fatalf("got error: %v", err) - } - d := int32(d64) - if d != v { - t.Fatalf("expected is[%d] to be %d from GetInt32Slice but got: %d", i, d, v) - } - } -} - -func TestI32SAsSliceValue(t *testing.T) { - var i32s []int32 - f := setUpI32SFlagSet(&i32s) - - in := []string{"1", "2"} - argfmt := "--is=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"3"}) - } - }) - if len(i32s) != 1 || i32s[0] != 3 { - t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", i32s) - } -} - -func TestI32SCalledTwice(t *testing.T) { - var is []int32 - f := setUpI32SFlagSet(&is) - - in := []string{"1,2", "3"} - expected := []int32{1, 2, 3} - argfmt := "--is=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - if expected[i] != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/int64_slice.go b/vendor/github.com/spf13/pflag/int64_slice.go deleted file mode 100644 index 25464638f3..0000000000 --- a/vendor/github.com/spf13/pflag/int64_slice.go +++ /dev/null @@ -1,166 +0,0 @@ -package pflag - -import ( - "fmt" - "strconv" - "strings" -) - -// -- int64Slice Value -type int64SliceValue struct { - value *[]int64 - changed bool -} - -func newInt64SliceValue(val []int64, p *[]int64) *int64SliceValue { - isv := new(int64SliceValue) - isv.value = p - *isv.value = val - return isv -} - -func (s *int64SliceValue) Set(val string) error { - ss := strings.Split(val, ",") - out := make([]int64, len(ss)) - for i, d := range ss { - var err error - out[i], err = strconv.ParseInt(d, 0, 64) - if err != nil { - return err - } - - } - if !s.changed { - *s.value = out - } else { - *s.value = append(*s.value, out...) - } - s.changed = true - return nil -} - -func (s *int64SliceValue) Type() string { - return "int64Slice" -} - -func (s *int64SliceValue) String() string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = fmt.Sprintf("%d", d) - } - return "[" + strings.Join(out, ",") + "]" -} - -func (s *int64SliceValue) fromString(val string) (int64, error) { - return strconv.ParseInt(val, 0, 64) -} - -func (s *int64SliceValue) toString(val int64) string { - return fmt.Sprintf("%d", val) -} - -func (s *int64SliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *int64SliceValue) Replace(val []string) error { - out := make([]int64, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *int64SliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - -func int64SliceConv(val string) (interface{}, error) { - val = strings.Trim(val, "[]") - // Empty string would cause a slice with one (empty) entry - if len(val) == 0 { - return []int64{}, nil - } - ss := strings.Split(val, ",") - out := make([]int64, len(ss)) - for i, d := range ss { - var err error - out[i], err = strconv.ParseInt(d, 0, 64) - if err != nil { - return nil, err - } - - } - return out, nil -} - -// GetInt64Slice return the []int64 value of a flag with the given name -func (f *FlagSet) GetInt64Slice(name string) ([]int64, error) { - val, err := f.getFlagType(name, "int64Slice", int64SliceConv) - if err != nil { - return []int64{}, err - } - return val.([]int64), nil -} - -// Int64SliceVar defines a int64Slice flag with specified name, default value, and usage string. -// The argument p points to a []int64 variable in which to store the value of the flag. -func (f *FlagSet) Int64SliceVar(p *[]int64, name string, value []int64, usage string) { - f.VarP(newInt64SliceValue(value, p), name, "", usage) -} - -// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) { - f.VarP(newInt64SliceValue(value, p), name, shorthand, usage) -} - -// Int64SliceVar defines a int64[] flag with specified name, default value, and usage string. -// The argument p points to a int64[] variable in which to store the value of the flag. -func Int64SliceVar(p *[]int64, name string, value []int64, usage string) { - CommandLine.VarP(newInt64SliceValue(value, p), name, "", usage) -} - -// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash. -func Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) { - CommandLine.VarP(newInt64SliceValue(value, p), name, shorthand, usage) -} - -// Int64Slice defines a []int64 flag with specified name, default value, and usage string. -// The return value is the address of a []int64 variable that stores the value of the flag. -func (f *FlagSet) Int64Slice(name string, value []int64, usage string) *[]int64 { - p := []int64{} - f.Int64SliceVarP(&p, name, "", value, usage) - return &p -} - -// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 { - p := []int64{} - f.Int64SliceVarP(&p, name, shorthand, value, usage) - return &p -} - -// Int64Slice defines a []int64 flag with specified name, default value, and usage string. -// The return value is the address of a []int64 variable that stores the value of the flag. -func Int64Slice(name string, value []int64, usage string) *[]int64 { - return CommandLine.Int64SliceP(name, "", value, usage) -} - -// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash. -func Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 { - return CommandLine.Int64SliceP(name, shorthand, value, usage) -} diff --git a/vendor/github.com/spf13/pflag/int64_slice_test.go b/vendor/github.com/spf13/pflag/int64_slice_test.go deleted file mode 100644 index 09805c7678..0000000000 --- a/vendor/github.com/spf13/pflag/int64_slice_test.go +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "fmt" - "strconv" - "strings" - "testing" -) - -func setUpI64SFlagSet(isp *[]int64) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Int64SliceVar(isp, "is", []int64{}, "Command separated list!") - return f -} - -func setUpI64SFlagSetWithDefault(isp *[]int64) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.Int64SliceVar(isp, "is", []int64{0, 1}, "Command separated list!") - return f -} - -func TestEmptyI64S(t *testing.T) { - var is []int64 - f := setUpI64SFlagSet(&is) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getI64S, err := f.GetInt64Slice("is") - if err != nil { - t.Fatal("got an error from GetInt64Slice():", err) - } - if len(getI64S) != 0 { - t.Fatalf("got is %v with len=%d but expected length=0", getI64S, len(getI64S)) - } -} - -func TestI64S(t *testing.T) { - var is []int64 - f := setUpI64SFlagSet(&is) - - vals := []string{"1", "2", "4", "3"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.ParseInt(vals[i], 0, 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d", i, vals[i], v) - } - } - getI64S, err := f.GetInt64Slice("is") - if err != nil { - t.Fatalf("got error: %v", err) - } - for i, v := range getI64S { - d, err := strconv.ParseInt(vals[i], 0, 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %s but got: %d from GetInt64Slice", i, vals[i], v) - } - } -} - -func TestI64SDefault(t *testing.T) { - var is []int64 - f := setUpI64SFlagSetWithDefault(&is) - - vals := []string{"0", "1"} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.ParseInt(vals[i], 0, 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getI64S, err := f.GetInt64Slice("is") - if err != nil { - t.Fatal("got an error from GetInt64Slice():", err) - } - for i, v := range getI64S { - d, err := strconv.ParseInt(vals[i], 0, 64) - if err != nil { - t.Fatal("got an error from GetInt64Slice():", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d from GetInt64Slice but got: %d", i, d, v) - } - } -} - -func TestI64SWithDefault(t *testing.T) { - var is []int64 - f := setUpI64SFlagSetWithDefault(&is) - - vals := []string{"1", "2"} - arg := fmt.Sprintf("--is=%s", strings.Join(vals, ",")) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - d, err := strconv.ParseInt(vals[i], 0, 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, d, v) - } - } - - getI64S, err := f.GetInt64Slice("is") - if err != nil { - t.Fatal("got an error from GetInt64Slice():", err) - } - for i, v := range getI64S { - d, err := strconv.ParseInt(vals[i], 0, 64) - if err != nil { - t.Fatalf("got error: %v", err) - } - if d != v { - t.Fatalf("expected is[%d] to be %d from GetInt64Slice but got: %d", i, d, v) - } - } -} - -func TestI64SAsSliceValue(t *testing.T) { - var i64s []int64 - f := setUpI64SFlagSet(&i64s) - - in := []string{"1", "2"} - argfmt := "--is=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"3"}) - } - }) - if len(i64s) != 1 || i64s[0] != 3 { - t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", i64s) - } -} - -func TestI64SCalledTwice(t *testing.T) { - var is []int64 - f := setUpI64SFlagSet(&is) - - in := []string{"1,2", "3"} - expected := []int64{1, 2, 3} - argfmt := "--is=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range is { - if expected[i] != v { - t.Fatalf("expected is[%d] to be %d but got: %d", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/int_slice.go b/vendor/github.com/spf13/pflag/int_slice.go index e71c39d91a..1e7c9edde9 100644 --- a/vendor/github.com/spf13/pflag/int_slice.go +++ b/vendor/github.com/spf13/pflag/int_slice.go @@ -51,36 +51,6 @@ func (s *intSliceValue) String() string { return "[" + strings.Join(out, ",") + "]" } -func (s *intSliceValue) Append(val string) error { - i, err := strconv.Atoi(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *intSliceValue) Replace(val []string) error { - out := make([]int, len(val)) - for i, d := range val { - var err error - out[i], err = strconv.Atoi(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *intSliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = strconv.Itoa(d) - } - return out -} - func intSliceConv(val string) (interface{}, error) { val = strings.Trim(val, "[]") // Empty string would cause a slice with one (empty) entry diff --git a/vendor/github.com/spf13/pflag/ip_slice.go b/vendor/github.com/spf13/pflag/ip_slice.go index 775faae4fd..7dd196fe3f 100644 --- a/vendor/github.com/spf13/pflag/ip_slice.go +++ b/vendor/github.com/spf13/pflag/ip_slice.go @@ -72,47 +72,9 @@ func (s *ipSliceValue) String() string { return "[" + out + "]" } -func (s *ipSliceValue) fromString(val string) (net.IP, error) { - return net.ParseIP(strings.TrimSpace(val)), nil -} - -func (s *ipSliceValue) toString(val net.IP) string { - return val.String() -} - -func (s *ipSliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *ipSliceValue) Replace(val []string) error { - out := make([]net.IP, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *ipSliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - func ipSliceConv(val string) (interface{}, error) { val = strings.Trim(val, "[]") - // Empty string would cause a slice with one (empty) entry + // Emtpy string would cause a slice with one (empty) entry if len(val) == 0 { return []net.IP{}, nil } diff --git a/vendor/github.com/spf13/pflag/ip_slice_test.go b/vendor/github.com/spf13/pflag/ip_slice_test.go index d189276863..b0c681c5b2 100644 --- a/vendor/github.com/spf13/pflag/ip_slice_test.go +++ b/vendor/github.com/spf13/pflag/ip_slice_test.go @@ -141,29 +141,6 @@ func TestIPSCalledTwice(t *testing.T) { } } -func TestIPSAsSliceValue(t *testing.T) { - var ips []net.IP - f := setUpIPSFlagSet(&ips) - - in := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"} - argfmt := "--ips=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"192.168.1.2"}) - } - }) - if len(ips) != 1 || !ips[0].Equal(net.ParseIP("192.168.1.2")) { - t.Fatalf("Expected ss to be overwritten with '192.168.1.2', but got: %v", ips) - } -} - func TestIPSBadQuoting(t *testing.T) { tests := []struct { diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go index 4894af8180..fa7bc60187 100644 --- a/vendor/github.com/spf13/pflag/string_array.go +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -23,32 +23,6 @@ func (s *stringArrayValue) Set(val string) error { return nil } -func (s *stringArrayValue) Append(val string) error { - *s.value = append(*s.value, val) - return nil -} - -func (s *stringArrayValue) Replace(val []string) error { - out := make([]string, len(val)) - for i, d := range val { - var err error - out[i] = d - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *stringArrayValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = d - } - return out -} - func (s *stringArrayValue) Type() string { return "stringArray" } diff --git a/vendor/github.com/spf13/pflag/string_array_test.go b/vendor/github.com/spf13/pflag/string_array_test.go index 3c6d595873..1ceac8c6c6 100644 --- a/vendor/github.com/spf13/pflag/string_array_test.go +++ b/vendor/github.com/spf13/pflag/string_array_test.go @@ -193,29 +193,6 @@ func TestSAWithSpecialChar(t *testing.T) { } } -func TestSAAsSliceValue(t *testing.T) { - var sa []string - f := setUpSAFlagSet(&sa) - - in := []string{"1ns", "2ns"} - argfmt := "--sa=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"3ns"}) - } - }) - if len(sa) != 1 || sa[0] != "3ns" { - t.Fatalf("Expected ss to be overwritten with '3ns', but got: %v", sa) - } -} - func TestSAWithSquareBrackets(t *testing.T) { var sa []string f := setUpSAFlagSet(&sa) diff --git a/vendor/github.com/spf13/pflag/string_slice.go b/vendor/github.com/spf13/pflag/string_slice.go index 3cb2e69dba..0cd3ccc083 100644 --- a/vendor/github.com/spf13/pflag/string_slice.go +++ b/vendor/github.com/spf13/pflag/string_slice.go @@ -62,20 +62,6 @@ func (s *stringSliceValue) String() string { return "[" + str + "]" } -func (s *stringSliceValue) Append(val string) error { - *s.value = append(*s.value, val) - return nil -} - -func (s *stringSliceValue) Replace(val []string) error { - *s.value = val - return nil -} - -func (s *stringSliceValue) GetSlice() []string { - return *s.value -} - func stringSliceConv(sval string) (interface{}, error) { sval = sval[1 : len(sval)-1] // An empty string would cause a slice with one (empty) string @@ -98,7 +84,7 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) { // The argument p points to a []string variable in which to store the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// --ss="v1,v2" -ss="v3" // will result in // []string{"v1", "v2", "v3"} func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) { @@ -114,7 +100,7 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s // The argument p points to a []string variable in which to store the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// --ss="v1,v2" -ss="v3" // will result in // []string{"v1", "v2", "v3"} func StringSliceVar(p *[]string, name string, value []string, usage string) { @@ -130,7 +116,7 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage // The return value is the address of a []string variable that stores the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// --ss="v1,v2" -ss="v3" // will result in // []string{"v1", "v2", "v3"} func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { @@ -150,7 +136,7 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str // The return value is the address of a []string variable that stores the value of the flag. // Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly. // For example: -// --ss="v1,v2" --ss="v3" +// --ss="v1,v2" -ss="v3" // will result in // []string{"v1", "v2", "v3"} func StringSlice(name string, value []string, usage string) *[]string { diff --git a/vendor/github.com/spf13/pflag/string_slice_test.go b/vendor/github.com/spf13/pflag/string_slice_test.go index 9692461729..c41f3bd660 100644 --- a/vendor/github.com/spf13/pflag/string_slice_test.go +++ b/vendor/github.com/spf13/pflag/string_slice_test.go @@ -251,26 +251,3 @@ func TestSSWithSquareBrackets(t *testing.T) { } } } - -func TestSSAsSliceValue(t *testing.T) { - var ss []string - f := setUpSSFlagSet(&ss) - - in := []string{"one", "two"} - argfmt := "--ss=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"three"}) - } - }) - if len(ss) != 1 || ss[0] != "three" { - t.Fatalf("Expected ss to be overwritten with 'three', but got: %s", ss) - } -} diff --git a/vendor/github.com/spf13/pflag/string_to_int64.go b/vendor/github.com/spf13/pflag/string_to_int64.go deleted file mode 100644 index a807a04a0b..0000000000 --- a/vendor/github.com/spf13/pflag/string_to_int64.go +++ /dev/null @@ -1,149 +0,0 @@ -package pflag - -import ( - "bytes" - "fmt" - "strconv" - "strings" -) - -// -- stringToInt64 Value -type stringToInt64Value struct { - value *map[string]int64 - changed bool -} - -func newStringToInt64Value(val map[string]int64, p *map[string]int64) *stringToInt64Value { - ssv := new(stringToInt64Value) - ssv.value = p - *ssv.value = val - return ssv -} - -// Format: a=1,b=2 -func (s *stringToInt64Value) Set(val string) error { - ss := strings.Split(val, ",") - out := make(map[string]int64, len(ss)) - for _, pair := range ss { - kv := strings.SplitN(pair, "=", 2) - if len(kv) != 2 { - return fmt.Errorf("%s must be formatted as key=value", pair) - } - var err error - out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64) - if err != nil { - return err - } - } - if !s.changed { - *s.value = out - } else { - for k, v := range out { - (*s.value)[k] = v - } - } - s.changed = true - return nil -} - -func (s *stringToInt64Value) Type() string { - return "stringToInt64" -} - -func (s *stringToInt64Value) String() string { - var buf bytes.Buffer - i := 0 - for k, v := range *s.value { - if i > 0 { - buf.WriteRune(',') - } - buf.WriteString(k) - buf.WriteRune('=') - buf.WriteString(strconv.FormatInt(v, 10)) - i++ - } - return "[" + buf.String() + "]" -} - -func stringToInt64Conv(val string) (interface{}, error) { - val = strings.Trim(val, "[]") - // An empty string would cause an empty map - if len(val) == 0 { - return map[string]int64{}, nil - } - ss := strings.Split(val, ",") - out := make(map[string]int64, len(ss)) - for _, pair := range ss { - kv := strings.SplitN(pair, "=", 2) - if len(kv) != 2 { - return nil, fmt.Errorf("%s must be formatted as key=value", pair) - } - var err error - out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64) - if err != nil { - return nil, err - } - } - return out, nil -} - -// GetStringToInt64 return the map[string]int64 value of a flag with the given name -func (f *FlagSet) GetStringToInt64(name string) (map[string]int64, error) { - val, err := f.getFlagType(name, "stringToInt64", stringToInt64Conv) - if err != nil { - return map[string]int64{}, err - } - return val.(map[string]int64), nil -} - -// StringToInt64Var defines a string flag with specified name, default value, and usage string. -// The argument p point64s to a map[string]int64 variable in which to store the values of the multiple flags. -// The value of each argument will not try to be separated by comma -func (f *FlagSet) StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) { - f.VarP(newStringToInt64Value(value, p), name, "", usage) -} - -// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) { - f.VarP(newStringToInt64Value(value, p), name, shorthand, usage) -} - -// StringToInt64Var defines a string flag with specified name, default value, and usage string. -// The argument p point64s to a map[string]int64 variable in which to store the value of the flag. -// The value of each argument will not try to be separated by comma -func StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) { - CommandLine.VarP(newStringToInt64Value(value, p), name, "", usage) -} - -// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash. -func StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) { - CommandLine.VarP(newStringToInt64Value(value, p), name, shorthand, usage) -} - -// StringToInt64 defines a string flag with specified name, default value, and usage string. -// The return value is the address of a map[string]int64 variable that stores the value of the flag. -// The value of each argument will not try to be separated by comma -func (f *FlagSet) StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 { - p := map[string]int64{} - f.StringToInt64VarP(&p, name, "", value, usage) - return &p -} - -// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash. -func (f *FlagSet) StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 { - p := map[string]int64{} - f.StringToInt64VarP(&p, name, shorthand, value, usage) - return &p -} - -// StringToInt64 defines a string flag with specified name, default value, and usage string. -// The return value is the address of a map[string]int64 variable that stores the value of the flag. -// The value of each argument will not try to be separated by comma -func StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 { - return CommandLine.StringToInt64P(name, "", value, usage) -} - -// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash. -func StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 { - return CommandLine.StringToInt64P(name, shorthand, value, usage) -} diff --git a/vendor/github.com/spf13/pflag/string_to_int64_test.go b/vendor/github.com/spf13/pflag/string_to_int64_test.go deleted file mode 100644 index 2b3f29895b..0000000000 --- a/vendor/github.com/spf13/pflag/string_to_int64_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of ths2i source code s2i governed by a BSD-style -// license that can be found in the LICENSE file. - -package pflag - -import ( - "bytes" - "fmt" - "strconv" - "testing" -) - -func setUpS2I64FlagSet(s2ip *map[string]int64) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringToInt64Var(s2ip, "s2i", map[string]int64{}, "Command separated ls2it!") - return f -} - -func setUpS2I64FlagSetWithDefault(s2ip *map[string]int64) *FlagSet { - f := NewFlagSet("test", ContinueOnError) - f.StringToInt64Var(s2ip, "s2i", map[string]int64{"a": 1, "b": 2}, "Command separated ls2it!") - return f -} - -func createS2I64Flag(vals map[string]int64) string { - var buf bytes.Buffer - i := 0 - for k, v := range vals { - if i > 0 { - buf.WriteRune(',') - } - buf.WriteString(k) - buf.WriteRune('=') - buf.WriteString(strconv.FormatInt(v, 10)) - i++ - } - return buf.String() -} - -func TestEmptyS2I64(t *testing.T) { - var s2i map[string]int64 - f := setUpS2I64FlagSet(&s2i) - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - getS2I, err := f.GetStringToInt64("s2i") - if err != nil { - t.Fatal("got an error from GetStringToInt64():", err) - } - if len(getS2I) != 0 { - t.Fatalf("got s2i %v with len=%d but expected length=0", getS2I, len(getS2I)) - } -} - -func TestS2I64(t *testing.T) { - var s2i map[string]int64 - f := setUpS2I64FlagSet(&s2i) - - vals := map[string]int64{"a": 1, "b": 2, "d": 4, "c": 3} - arg := fmt.Sprintf("--s2i=%s", createS2I64Flag(vals)) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for k, v := range s2i { - if vals[k] != v { - t.Fatalf("expected s2i[%s] to be %d but got: %d", k, vals[k], v) - } - } - getS2I, err := f.GetStringToInt64("s2i") - if err != nil { - t.Fatalf("got error: %v", err) - } - for k, v := range getS2I { - if vals[k] != v { - t.Fatalf("expected s2i[%s] to be %d but got: %d from GetStringToInt64", k, vals[k], v) - } - } -} - -func TestS2I64Default(t *testing.T) { - var s2i map[string]int64 - f := setUpS2I64FlagSetWithDefault(&s2i) - - vals := map[string]int64{"a": 1, "b": 2} - - err := f.Parse([]string{}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for k, v := range s2i { - if vals[k] != v { - t.Fatalf("expected s2i[%s] to be %d but got: %d", k, vals[k], v) - } - } - - getS2I, err := f.GetStringToInt64("s2i") - if err != nil { - t.Fatal("got an error from GetStringToInt64():", err) - } - for k, v := range getS2I { - if vals[k] != v { - t.Fatalf("expected s2i[%s] to be %d from GetStringToInt64 but got: %d", k, vals[k], v) - } - } -} - -func TestS2I64WithDefault(t *testing.T) { - var s2i map[string]int64 - f := setUpS2I64FlagSetWithDefault(&s2i) - - vals := map[string]int64{"a": 1, "b": 2} - arg := fmt.Sprintf("--s2i=%s", createS2I64Flag(vals)) - err := f.Parse([]string{arg}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for k, v := range s2i { - if vals[k] != v { - t.Fatalf("expected s2i[%s] to be %d but got: %d", k, vals[k], v) - } - } - - getS2I, err := f.GetStringToInt64("s2i") - if err != nil { - t.Fatal("got an error from GetStringToInt64():", err) - } - for k, v := range getS2I { - if vals[k] != v { - t.Fatalf("expected s2i[%s] to be %d from GetStringToInt64 but got: %d", k, vals[k], v) - } - } -} - -func TestS2I64CalledTwice(t *testing.T) { - var s2i map[string]int64 - f := setUpS2I64FlagSet(&s2i) - - in := []string{"a=1,b=2", "b=3"} - expected := map[string]int64{"a": 1, "b": 3} - argfmt := "--s2i=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - for i, v := range s2i { - if expected[i] != v { - t.Fatalf("expected s2i[%s] to be %d but got: %d", i, expected[i], v) - } - } -} diff --git a/vendor/github.com/spf13/pflag/uint_slice.go b/vendor/github.com/spf13/pflag/uint_slice.go index 5fa924835e..edd94c600a 100644 --- a/vendor/github.com/spf13/pflag/uint_slice.go +++ b/vendor/github.com/spf13/pflag/uint_slice.go @@ -50,48 +50,6 @@ func (s *uintSliceValue) String() string { return "[" + strings.Join(out, ",") + "]" } -func (s *uintSliceValue) fromString(val string) (uint, error) { - t, err := strconv.ParseUint(val, 10, 0) - if err != nil { - return 0, err - } - return uint(t), nil -} - -func (s *uintSliceValue) toString(val uint) string { - return fmt.Sprintf("%d", val) -} - -func (s *uintSliceValue) Append(val string) error { - i, err := s.fromString(val) - if err != nil { - return err - } - *s.value = append(*s.value, i) - return nil -} - -func (s *uintSliceValue) Replace(val []string) error { - out := make([]uint, len(val)) - for i, d := range val { - var err error - out[i], err = s.fromString(d) - if err != nil { - return err - } - } - *s.value = out - return nil -} - -func (s *uintSliceValue) GetSlice() []string { - out := make([]string, len(*s.value)) - for i, d := range *s.value { - out[i] = s.toString(d) - } - return out -} - func uintSliceConv(val string) (interface{}, error) { val = strings.Trim(val, "[]") // Empty string would cause a slice with one (empty) entry diff --git a/vendor/github.com/spf13/pflag/uint_slice_test.go b/vendor/github.com/spf13/pflag/uint_slice_test.go index d0da4d0757..db1a19dc2d 100644 --- a/vendor/github.com/spf13/pflag/uint_slice_test.go +++ b/vendor/github.com/spf13/pflag/uint_slice_test.go @@ -140,29 +140,6 @@ func TestUISWithDefault(t *testing.T) { } } -func TestUISAsSliceValue(t *testing.T) { - var uis []uint - f := setUpUISFlagSet(&uis) - - in := []string{"1", "2"} - argfmt := "--uis=%s" - arg1 := fmt.Sprintf(argfmt, in[0]) - arg2 := fmt.Sprintf(argfmt, in[1]) - err := f.Parse([]string{arg1, arg2}) - if err != nil { - t.Fatal("expected no error; got", err) - } - - f.VisitAll(func(f *Flag) { - if val, ok := f.Value.(SliceValue); ok { - _ = val.Replace([]string{"3"}) - } - }) - if len(uis) != 1 || uis[0] != 3 { - t.Fatalf("Expected ss to be overwritten with '3.1', but got: %v", uis) - } -} - func TestUISCalledTwice(t *testing.T) { var uis []uint f := setUpUISFlagSet(&uis) diff --git a/vendor/golang.org/x/tools/cmd/auth/authtest/authtest.go b/vendor/golang.org/x/tools/cmd/auth/authtest/authtest.go deleted file mode 100644 index 263eed828c..0000000000 --- a/vendor/golang.org/x/tools/cmd/auth/authtest/authtest.go +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// authtest is a diagnostic tool for implementations of the GOAUTH protocol -// described in https://golang.org/issue/26232. -// -// It accepts a single URL as an argument, and executes the GOAUTH protocol to -// fetch and display the headers for that URL. -// -// CAUTION: authtest logs the GOAUTH responses, which may include user -// credentials, to stderr. Do not post its output unless you are certain that -// all of the credentials involved are fake! -package main - -import ( - "bufio" - "bytes" - "flag" - "fmt" - "io" - "log" - "net/http" - "net/textproto" - "net/url" - "os" - "os/exec" - "path/filepath" - "strings" -) - -var v = flag.Bool("v", false, "if true, log GOAUTH responses to stderr") - -func main() { - log.SetFlags(log.LstdFlags | log.Lshortfile) - flag.Parse() - args := flag.Args() - if len(args) != 1 { - log.Fatalf("usage: [GOAUTH=CMD...] %s URL", filepath.Base(os.Args[0])) - } - - resp := try(args[0], nil) - if resp.StatusCode == http.StatusOK { - return - } - - resp = try(args[0], resp) - if resp.StatusCode != http.StatusOK { - os.Exit(1) - } -} - -func try(url string, prev *http.Response) *http.Response { - req := new(http.Request) - if prev != nil { - *req = *prev.Request - } else { - var err error - req, err = http.NewRequest("HEAD", os.Args[1], nil) - if err != nil { - log.Fatal(err) - } - } - -goauth: - for _, argList := range strings.Split(os.Getenv("GOAUTH"), ";") { - // TODO(golang.org/issue/26849): If we escape quoted strings in GOFLAGS, use - // the same quoting here. - args := strings.Split(argList, " ") - if len(args) == 0 || args[0] == "" { - log.Fatalf("invalid or empty command in GOAUTH") - } - - creds, err := getCreds(args, prev) - if err != nil { - log.Fatal(err) - } - for _, c := range creds { - if c.Apply(req) { - fmt.Fprintf(os.Stderr, "# request to %s\n", req.URL) - fmt.Fprintf(os.Stderr, "%s %s %s\n", req.Method, req.URL, req.Proto) - req.Header.Write(os.Stderr) - fmt.Fprintln(os.Stderr) - break goauth - } - } - } - - resp, err := http.DefaultClient.Do(req) - if err != nil { - log.Fatal(err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK && resp.StatusCode < 400 || resp.StatusCode > 500 { - log.Fatalf("unexpected status: %v", resp.Status) - } - - fmt.Fprintf(os.Stderr, "# response from %s\n", resp.Request.URL) - formatHead(os.Stderr, resp) - return resp -} - -func formatHead(out io.Writer, resp *http.Response) { - fmt.Fprintf(out, "%s %s\n", resp.Proto, resp.Status) - if err := resp.Header.Write(out); err != nil { - log.Fatal(err) - } - fmt.Fprintln(out) -} - -type Cred struct { - URLPrefixes []*url.URL - Header http.Header -} - -func (c Cred) Apply(req *http.Request) bool { - if req.URL == nil { - return false - } - ok := false - for _, prefix := range c.URLPrefixes { - if prefix.Host == req.URL.Host && - (req.URL.Path == prefix.Path || - (strings.HasPrefix(req.URL.Path, prefix.Path) && - (strings.HasSuffix(prefix.Path, "/") || - req.URL.Path[len(prefix.Path)] == '/'))) { - ok = true - break - } - } - if !ok { - return false - } - - for k, vs := range c.Header { - req.Header.Del(k) - for _, v := range vs { - req.Header.Add(k, v) - } - } - return true -} - -func (c Cred) String() string { - var buf strings.Builder - for _, u := range c.URLPrefixes { - fmt.Fprintln(&buf, u) - } - buf.WriteString("\n") - c.Header.Write(&buf) - buf.WriteString("\n") - return buf.String() -} - -func getCreds(args []string, resp *http.Response) ([]Cred, error) { - cmd := exec.Command(args[0], args[1:]...) - cmd.Stderr = os.Stderr - - if resp != nil { - u := *resp.Request.URL - u.RawQuery = "" - cmd.Args = append(cmd.Args, u.String()) - } - - var head strings.Builder - if resp != nil { - formatHead(&head, resp) - } - cmd.Stdin = strings.NewReader(head.String()) - - fmt.Fprintf(os.Stderr, "# %s\n", strings.Join(cmd.Args, " ")) - out, err := cmd.Output() - if err != nil { - return nil, fmt.Errorf("%s: %v", strings.Join(cmd.Args, " "), err) - } - os.Stderr.Write(out) - os.Stderr.WriteString("\n") - - var creds []Cred - r := textproto.NewReader(bufio.NewReader(bytes.NewReader(out))) - line := 0 -readLoop: - for { - var prefixes []*url.URL - for { - prefix, err := r.ReadLine() - if err == io.EOF { - if len(prefixes) > 0 { - return nil, fmt.Errorf("line %d: %v", line, io.ErrUnexpectedEOF) - } - break readLoop - } - line++ - - if prefix == "" { - if len(prefixes) == 0 { - return nil, fmt.Errorf("line %d: unexpected newline", line) - } - break - } - u, err := url.Parse(prefix) - if err != nil { - return nil, fmt.Errorf("line %d: malformed URL: %v", line, err) - } - if u.Scheme != "https" { - return nil, fmt.Errorf("line %d: non-HTTPS URL %q", line, prefix) - } - if len(u.RawQuery) > 0 { - return nil, fmt.Errorf("line %d: unexpected query string in URL %q", line, prefix) - } - if len(u.Fragment) > 0 { - return nil, fmt.Errorf("line %d: unexpected fragment in URL %q", line, prefix) - } - prefixes = append(prefixes, u) - } - - header, err := r.ReadMIMEHeader() - if err != nil { - return nil, fmt.Errorf("headers at line %d: %v", line, err) - } - if len(header) > 0 { - creds = append(creds, Cred{ - URLPrefixes: prefixes, - Header: http.Header(header), - }) - } - } - - return creds, nil -} diff --git a/vendor/golang.org/x/tools/cmd/auth/cookieauth/cookieauth.go b/vendor/golang.org/x/tools/cmd/auth/cookieauth/cookieauth.go deleted file mode 100644 index 37e8d6e182..0000000000 --- a/vendor/golang.org/x/tools/cmd/auth/cookieauth/cookieauth.go +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// cookieauth uses a “Netscape cookie file” to implement the GOAUTH protocol -// described in https://golang.org/issue/26232. -// It expects the location of the file as the first command-line argument. -// -// Example GOAUTH usage: -// export GOAUTH="cookieauth $(git config --get http.cookieFile)" -// -// See http://www.cookiecentral.com/faq/#3.5 for a description of the Netscape -// cookie file format. -package main - -import ( - "bufio" - "fmt" - "io" - "log" - "net/http" - "net/http/cookiejar" - "net/url" - "os" - "strconv" - "strings" - "time" - "unicode" -) - -func main() { - if len(os.Args) < 2 { - fmt.Fprintf(os.Stderr, "usage: %s COOKIEFILE [URL]\n", os.Args[0]) - os.Exit(2) - } - - log.SetPrefix("cookieauth: ") - - f, err := os.Open(os.Args[1]) - if err != nil { - log.Fatalf("failed to read cookie file: %v\n", os.Args[1]) - os.Exit(1) - } - defer f.Close() - - var ( - targetURL *url.URL - targetURLs = map[string]*url.URL{} - ) - if len(os.Args) == 3 { - targetURL, err = url.ParseRequestURI(os.Args[2]) - if err != nil { - log.Fatalf("invalid request URI (%v): %q\n", err, os.Args[2]) - } - targetURLs[targetURL.String()] = targetURL - } else if len(os.Args) > 3 { - // Extra arguments were passed: maybe the protocol was expanded? - // We don't know how to interpret the request, so ignore it. - return - } - - entries, err := parseCookieFile(f.Name(), f) - if err != nil { - log.Fatalf("error reading cookie file: %v\n", f.Name()) - } - - jar, err := cookiejar.New(nil) - if err != nil { - log.Fatalf("failed to initialize cookie jar: %v\n", err) - } - - for _, e := range entries { - u := &url.URL{ - Scheme: "https", - Host: e.Host, - Path: e.Cookie.Path, - } - - if targetURL == nil { - targetURLs[u.String()] = u - } - - jar.SetCookies(u, []*http.Cookie{&e.Cookie}) - } - - for _, u := range targetURLs { - req := &http.Request{URL: u, Header: make(http.Header)} - for _, c := range jar.Cookies(req.URL) { - req.AddCookie(c) - } - fmt.Printf("%s\n\n", u) - req.Header.Write(os.Stdout) - fmt.Println() - } -} - -type Entry struct { - Host string - Cookie http.Cookie -} - -// parseCookieFile parses a Netscape cookie file as described in -// http://www.cookiecentral.com/faq/#3.5. -func parseCookieFile(name string, r io.Reader) ([]*Entry, error) { - var entries []*Entry - s := bufio.NewScanner(r) - line := 0 - for s.Scan() { - line++ - text := strings.TrimSpace(s.Text()) - if len(text) < 2 || (text[0] == '#' && unicode.IsSpace(rune(text[1]))) { - continue - } - - e, err := parseCookieLine(text) - if err != nil { - log.Printf("%s:%d: %v\n", name, line, err) - continue - } - entries = append(entries, e) - } - return entries, s.Err() -} - -func parseCookieLine(line string) (*Entry, error) { - f := strings.Fields(line) - if len(f) < 7 { - return nil, fmt.Errorf("found %d columns; want 7", len(f)) - } - - e := new(Entry) - c := &e.Cookie - - if domain := f[0]; strings.HasPrefix(domain, "#HttpOnly_") { - c.HttpOnly = true - e.Host = strings.TrimPrefix(domain[10:], ".") - } else { - e.Host = strings.TrimPrefix(domain, ".") - } - - isDomain, err := strconv.ParseBool(f[1]) - if err != nil { - return nil, fmt.Errorf("non-boolean domain flag: %v", err) - } - if isDomain { - c.Domain = e.Host - } - - c.Path = f[2] - - c.Secure, err = strconv.ParseBool(f[3]) - if err != nil { - return nil, fmt.Errorf("non-boolean secure flag: %v", err) - } - - expiration, err := strconv.ParseInt(f[4], 10, 64) - if err != nil { - return nil, fmt.Errorf("malformed expiration: %v", err) - } - c.Expires = time.Unix(expiration, 0) - - c.Name = f[5] - c.Value = f[6] - - return e, nil -} diff --git a/vendor/golang.org/x/tools/cmd/auth/gitauth/gitauth.go b/vendor/golang.org/x/tools/cmd/auth/gitauth/gitauth.go deleted file mode 100644 index b481fe6b99..0000000000 --- a/vendor/golang.org/x/tools/cmd/auth/gitauth/gitauth.go +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// gitauth uses 'git credential' to implement the GOAUTH protocol described in -// https://golang.org/issue/26232. It expects an absolute path to the working -// directory for the 'git' command as the first command-line argument. -// -// Example GOAUTH usage: -// export GOAUTH="gitauth $HOME" -// -// See https://git-scm.com/docs/gitcredentials or run 'man gitcredentials' for -// information on how to configure 'git credential'. -package main - -import ( - "bytes" - "fmt" - "log" - "net/http" - "net/url" - "os" - "os/exec" - "path/filepath" - "strings" -) - -func main() { - if len(os.Args) < 2 || !filepath.IsAbs(os.Args[1]) { - fmt.Fprintf(os.Stderr, "usage: %s WORKDIR [URL]", os.Args[0]) - os.Exit(2) - } - - log.SetPrefix("gitauth: ") - - if len(os.Args) != 3 { - // No explicit URL was passed on the command line, but 'git credential' - // provides no way to enumerate existing credentials. - // Wait for a request for a specific URL. - return - } - - u, err := url.ParseRequestURI(os.Args[2]) - if err != nil { - log.Fatalf("invalid request URI (%v): %q\n", err, os.Args[1]) - } - - var ( - prefix *url.URL - lastHeader http.Header - lastStatus = http.StatusUnauthorized - ) - for lastStatus == http.StatusUnauthorized { - cmd := exec.Command("git", "credential", "fill") - - // We don't want to execute a 'git' command in an arbitrary directory, since - // that opens up a number of config-injection attacks (for example, - // https://golang.org/issue/29230). Instead, we have the user configure a - // directory explicitly on the command line. - cmd.Dir = os.Args[1] - - cmd.Stdin = strings.NewReader(fmt.Sprintf("url=%s\n", u)) - cmd.Stderr = os.Stderr - out, err := cmd.Output() - if err != nil { - log.Fatalf("'git credential fill' failed: %v\n", err) - } - - prefix = new(url.URL) - var username, password string - lines := strings.Split(string(out), "\n") - for _, line := range lines { - frags := strings.SplitN(line, "=", 2) - if len(frags) != 2 { - continue // Ignore unrecognized response lines. - } - switch strings.TrimSpace(frags[0]) { - case "protocol": - prefix.Scheme = frags[1] - case "host": - prefix.Host = frags[1] - case "path": - prefix.Path = frags[1] - case "username": - username = frags[1] - case "password": - password = frags[1] - case "url": - // Write to a local variable instead of updating prefix directly: - // if the url field is malformed, we don't want to invalidate - // information parsed from the protocol, host, and path fields. - u, err := url.ParseRequestURI(frags[1]) - if err == nil { - prefix = u - } else { - log.Printf("malformed URL from 'git credential fill' (%v): %q\n", err, frags[1]) - // Proceed anyway: we might be able to parse the prefix from other fields of the response. - } - } - } - - // Double-check that the URL Git gave us is a prefix of the one we requested. - if !strings.HasPrefix(u.String(), prefix.String()) { - log.Fatalf("requested a credential for %q, but 'git credential fill' provided one for %q\n", u, prefix) - } - - // Send a HEAD request to try to detect whether the credential is valid. - // If the user just typed in a correct password and has caching enabled, - // we don't want to nag them for it again the next time they run a 'go' command. - req, err := http.NewRequest("HEAD", u.String(), nil) - if err != nil { - log.Fatalf("internal error constructing HTTP HEAD request: %v\n", err) - } - req.SetBasicAuth(username, password) - lastHeader = req.Header - resp, err := http.DefaultClient.Do(req) - if err != nil { - log.Printf("HTTPS HEAD request failed to connect: %v\n", err) - // Couldn't verify the credential, but we have no evidence that it is invalid either. - // Proceed, but don't update git's credential cache. - break - } - lastStatus = resp.StatusCode - - if resp.StatusCode != http.StatusOK { - log.Printf("%s: %v %s\n", u, resp.StatusCode, http.StatusText(resp.StatusCode)) - } - - if resp.StatusCode == http.StatusOK || resp.StatusCode == http.StatusUnauthorized { - // We learned something about the credential: it either worked or it was invalid. - // Approve or reject the credential (on a best-effort basis) - // so that the git credential helper can update its cache as appropriate. - action := "approve" - if resp.StatusCode != http.StatusOK { - action = "reject" - } - cmd = exec.Command("git", "credential", action) - cmd.Stderr = os.Stderr - cmd.Stdout = os.Stderr - cmd.Stdin = bytes.NewReader(out) - _ = cmd.Run() - } - } - - // Write out the credential in the format expected by the 'go' command. - fmt.Printf("%s\n\n", prefix) - lastHeader.Write(os.Stdout) - fmt.Println() -} diff --git a/vendor/golang.org/x/tools/cmd/auth/netrcauth/netrcauth.go b/vendor/golang.org/x/tools/cmd/auth/netrcauth/netrcauth.go deleted file mode 100644 index 1855cfa24b..0000000000 --- a/vendor/golang.org/x/tools/cmd/auth/netrcauth/netrcauth.go +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// netrcauth uses a .netrc file (or _netrc file on Windows) to implement the -// GOAUTH protocol described in https://golang.org/issue/26232. -// It expects the location of the file as the first command-line argument. -// -// Example GOAUTH usage: -// export GOAUTH="netrcauth $HOME/.netrc" -// -// See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html -// or run 'man 5 netrc' for a description of the .netrc file format. -package main - -import ( - "fmt" - "io/ioutil" - "log" - "net/http" - "net/url" - "os" - "strings" -) - -func main() { - if len(os.Args) < 2 { - fmt.Fprintf(os.Stderr, "usage: %s NETRCFILE [URL]", os.Args[0]) - os.Exit(2) - } - - log.SetPrefix("netrcauth: ") - - if len(os.Args) != 2 { - // An explicit URL was passed on the command line, but netrcauth does not - // have any URL-specific output: it dumps the entire .netrc file at the - // first call. - return - } - - path := os.Args[1] - - data, err := ioutil.ReadFile(path) - if err != nil { - if os.IsNotExist(err) { - return - } - log.Fatalf("failed to read %s: %v\n", path, err) - } - - u := &url.URL{Scheme: "https"} - lines := parseNetrc(string(data)) - for _, l := range lines { - u.Host = l.machine - fmt.Printf("%s\n\n", u) - - req := &http.Request{Header: make(http.Header)} - req.SetBasicAuth(l.login, l.password) - req.Header.Write(os.Stdout) - fmt.Println() - } -} - -// The following functions were extracted from src/cmd/go/internal/web2/web.go -// as of https://golang.org/cl/161698. - -type netrcLine struct { - machine string - login string - password string -} - -func parseNetrc(data string) []netrcLine { - // See https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html - // for documentation on the .netrc format. - var nrc []netrcLine - var l netrcLine - inMacro := false - for _, line := range strings.Split(data, "\n") { - if inMacro { - if line == "" { - inMacro = false - } - continue - } - - f := strings.Fields(line) - i := 0 - for ; i < len(f)-1; i += 2 { - // Reset at each "machine" token. - // “The auto-login process searches the .netrc file for a machine token - // that matches […]. Once a match is made, the subsequent .netrc tokens - // are processed, stopping when the end of file is reached or another - // machine or a default token is encountered.” - switch f[i] { - case "machine": - l = netrcLine{machine: f[i+1]} - case "default": - break - case "login": - l.login = f[i+1] - case "password": - l.password = f[i+1] - case "macdef": - // “A macro is defined with the specified name; its contents begin with - // the next .netrc line and continue until a null line (consecutive - // new-line characters) is encountered.” - inMacro = true - } - if l.machine != "" && l.login != "" && l.password != "" { - nrc = append(nrc, l) - l = netrcLine{} - } - } - - if i < len(f) && f[i] == "default" { - // “There can be only one default token, and it must be after all machine tokens.” - break - } - } - - return nrc -} diff --git a/vendor/golang.org/x/tools/cmd/callgraph/main_test.go b/vendor/golang.org/x/tools/cmd/callgraph/main_test.go index 6aeae6f7d0..54953c7076 100644 --- a/vendor/golang.org/x/tools/cmd/callgraph/main_test.go +++ b/vendor/golang.org/x/tools/cmd/callgraph/main_test.go @@ -17,8 +17,6 @@ import ( "path/filepath" "strings" "testing" - - "golang.org/x/tools/internal/testenv" ) func init() { @@ -34,8 +32,6 @@ func init() { } func TestCallgraph(t *testing.T) { - testenv.NeedsTool(t, "go") - gopath, err := filepath.Abs("testdata") if err != nil { t.Fatal(err) diff --git a/vendor/golang.org/x/tools/cmd/compilebench/main.go b/vendor/golang.org/x/tools/cmd/compilebench/main.go index f66cf87651..4d3b74ef74 100644 --- a/vendor/golang.org/x/tools/cmd/compilebench/main.go +++ b/vendor/golang.org/x/tools/cmd/compilebench/main.go @@ -22,21 +22,12 @@ // -compileflags 'list' // Pass the space-separated list of flags to the compilation. // -// -link exe -// Use exe as the path to the cmd/link binary. -// -// -linkflags 'list' -// Pass the space-separated list of flags to the linker. -// // -count n // Run each benchmark n times (default 1). // // -cpuprofile file // Write a CPU profile of the compiler to file. // -// -go path -// Path to "go" command (default "go"). -// // -memprofile file // Write a memory profile of the compiler to file. // @@ -46,15 +37,12 @@ // -obj // Report object file statistics. // -// -pkg pkg +// -pkg // Benchmark compiling a single package. // // -run regexp // Only run benchmarks with names matching regexp. // -// -short -// Skip long-running benchmarks. -// // Although -cpuprofile and -memprofile are intended to write a // combined profile for all the executed benchmarks to file, // today they write only the profile for the last benchmark executed. @@ -96,7 +84,6 @@ import ( var ( goroot string compiler string - linker string runRE *regexp.Regexp is6g bool ) @@ -107,8 +94,6 @@ var ( flagObj = flag.Bool("obj", false, "report object file stats") flagCompiler = flag.String("compile", "", "use `exe` as the cmd/compile binary") flagCompilerFlags = flag.String("compileflags", "", "additional `flags` to pass to compile") - flagLinker = flag.String("link", "", "use `exe` as the cmd/link binary") - flagLinkerFlags = flag.String("linkflags", "", "additional `flags` to pass to link") flagRun = flag.String("run", "", "run benchmarks matching `regexp`") flagCount = flag.Int("count", 1, "run benchmarks `n` times") flagCpuprofile = flag.String("cpuprofile", "", "write CPU profile to `file`") @@ -118,33 +103,24 @@ var ( flagShort = flag.Bool("short", false, "skip long-running benchmarks") ) -type test struct { +var tests = []struct { name string - r runner -} - -type runner interface { - long() bool - run(name string, count int) error -} - -var tests = []test{ - {"BenchmarkTemplate", compile{"html/template"}}, - {"BenchmarkUnicode", compile{"unicode"}}, - {"BenchmarkGoTypes", compile{"go/types"}}, - {"BenchmarkCompiler", compile{"cmd/compile/internal/gc"}}, - {"BenchmarkSSA", compile{"cmd/compile/internal/ssa"}}, - {"BenchmarkFlate", compile{"compress/flate"}}, - {"BenchmarkGoParser", compile{"go/parser"}}, - {"BenchmarkReflect", compile{"reflect"}}, - {"BenchmarkTar", compile{"archive/tar"}}, - {"BenchmarkXML", compile{"encoding/xml"}}, - {"BenchmarkLinkCompiler", link{"cmd/compile", ""}}, - {"BenchmarkExternalLinkCompiler", link{"cmd/compile", "-linkmode=external"}}, - {"BenchmarkLinkWithoutDebugCompiler", link{"cmd/compile", "-w"}}, - {"BenchmarkStdCmd", goBuild{[]string{"std", "cmd"}}}, - {"BenchmarkHelloSize", size{"$GOROOT/test/helloworld.go", false}}, - {"BenchmarkCmdGoSize", size{"cmd/go", true}}, + dir string + long bool +}{ + {"BenchmarkTemplate", "html/template", false}, + {"BenchmarkUnicode", "unicode", false}, + {"BenchmarkGoTypes", "go/types", false}, + {"BenchmarkCompiler", "cmd/compile/internal/gc", false}, + {"BenchmarkSSA", "cmd/compile/internal/ssa", false}, + {"BenchmarkFlate", "compress/flate", false}, + {"BenchmarkGoParser", "go/parser", false}, + {"BenchmarkReflect", "reflect", false}, + {"BenchmarkTar", "archive/tar", false}, + {"BenchmarkXML", "encoding/xml", false}, + {"BenchmarkStdCmd", "", true}, + {"BenchmarkHelloSize", "", false}, + {"BenchmarkCmdGoSize", "", true}, } func usage() { @@ -172,23 +148,16 @@ func main() { compiler = *flagCompiler if compiler == "" { - var foundTool string - foundTool, compiler = toolPath("compile", "6g") - if foundTool == "6g" { + out, err := exec.Command(*flagGoCmd, "tool", "-n", "compile").CombinedOutput() + if err != nil { + out, err = exec.Command(*flagGoCmd, "tool", "-n", "6g").CombinedOutput() is6g = true + if err != nil { + out, err = exec.Command(*flagGoCmd, "tool", "-n", "compile").CombinedOutput() + log.Fatalf("go tool -n compiler: %v\n%s", err, out) + } } - } - - linker = *flagLinker - if linker == "" && !is6g { // TODO: Support 6l - _, linker = toolPath("link") - } - - if is6g { - *flagMemprofilerate = -1 - *flagAlloc = false - *flagCpuprofile = "" - *flagMemprofile = "" + compiler = strings.TrimSpace(string(out)) } if *flagRun != "" { @@ -199,117 +168,67 @@ func main() { runRE = r } - if *flagPackage != "" { - tests = []test{ - {"BenchmarkPkg", compile{*flagPackage}}, - {"BenchmarkPkgLink", link{*flagPackage, ""}}, - } - runRE = nil - } - for i := 0; i < *flagCount; i++ { + if *flagPackage != "" { + runBuild("BenchmarkPkg", *flagPackage, i) + continue + } for _, tt := range tests { - if tt.r.long() && *flagShort { + if tt.long && *flagShort { continue } if runRE == nil || runRE.MatchString(tt.name) { - if err := tt.r.run(tt.name, i); err != nil { - log.Printf("%s: %v", tt.name, err) - } + runBuild(tt.name, tt.dir, i) } } } } -func toolPath(names ...string) (found, path string) { - var out1 []byte - var err1 error - for i, name := range names { - out, err := exec.Command(*flagGoCmd, "tool", "-n", name).CombinedOutput() - if err == nil { - return name, strings.TrimSpace(string(out)) - } - if i == 0 { - out1, err1 = out, err - } - } - log.Fatalf("go tool -n %s: %v\n%s", names[0], err1, out1) - return "", "" -} - -type Pkg struct { - Dir string - GoFiles []string -} - -func goList(dir string) (*Pkg, error) { - var pkg Pkg - out, err := exec.Command(*flagGoCmd, "list", "-json", dir).Output() - if err != nil { - return nil, fmt.Errorf("go list -json %s: %v\n", dir, err) - } - if err := json.Unmarshal(out, &pkg); err != nil { - return nil, fmt.Errorf("go list -json %s: unmarshal: %v", dir, err) - } - return &pkg, nil -} - -func runCmd(name string, cmd *exec.Cmd) error { +func runCmd(name string, cmd *exec.Cmd) { start := time.Now() out, err := cmd.CombinedOutput() if err != nil { - return fmt.Errorf("%v\n%s", err, out) + log.Printf("%v: %v\n%s", name, err, out) + return } fmt.Printf("%s 1 %d ns/op\n", name, time.Since(start).Nanoseconds()) - return nil } -type goBuild struct{ pkgs []string } - -func (goBuild) long() bool { return true } - -func (r goBuild) run(name string, count int) error { +func runStdCmd() { args := []string{"build", "-a"} if *flagCompilerFlags != "" { args = append(args, "-gcflags", *flagCompilerFlags) } - args = append(args, r.pkgs...) + args = append(args, "std", "cmd") cmd := exec.Command(*flagGoCmd, args...) cmd.Dir = filepath.Join(goroot, "src") - return runCmd(name, cmd) + runCmd("BenchmarkStdCmd", cmd) } -type size struct { - // path is either a path to a file ("$GOROOT/test/helloworld.go") or a package path ("cmd/go"). - path string - isLong bool -} - -func (r size) long() bool { return r.isLong } - -func (r size) run(name string, count int) error { - if strings.HasPrefix(r.path, "$GOROOT/") { - r.path = goroot + "/" + r.path[len("$GOROOT/"):] - } - - cmd := exec.Command(*flagGoCmd, "build", "-o", "_compilebenchout_", r.path) +// path is either a path to a file ("$GOROOT/test/helloworld.go") or a package path ("cmd/go"). +func runSize(name, path string) { + cmd := exec.Command(*flagGoCmd, "build", "-o", "_compilebenchout_", path) cmd.Stdout = os.Stderr cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { - return err + log.Print(err) + return } defer os.Remove("_compilebenchout_") info, err := os.Stat("_compilebenchout_") if err != nil { - return err + log.Print(err) + return } out, err := exec.Command("size", "_compilebenchout_").CombinedOutput() if err != nil { - return fmt.Errorf("size: %v\n%s", err, out) + log.Printf("size: %v\n%s", err, out) + return } lines := strings.Split(string(out), "\n") if len(lines) < 2 { - return fmt.Errorf("not enough output from size: %s", out) + log.Printf("not enough output from size: %s", out) + return } f := strings.Fields(lines[1]) if strings.HasPrefix(lines[0], "__TEXT") && len(f) >= 2 { // OS X @@ -317,133 +236,78 @@ func (r size) run(name string, count int) error { } else if strings.Contains(lines[0], "bss") && len(f) >= 3 { fmt.Printf("%s 1 %s text-bytes %s data-bytes %s bss-bytes %v exe-bytes\n", name, f[0], f[1], f[2], info.Size()) } - return nil } -type compile struct{ dir string } - -func (compile) long() bool { return false } +func runBuild(name, dir string, count int) { + switch name { + case "BenchmarkStdCmd": + runStdCmd() + return + case "BenchmarkCmdGoSize": + runSize("BenchmarkCmdGoSize", "cmd/go") + return + case "BenchmarkHelloSize": + runSize("BenchmarkHelloSize", filepath.Join(goroot, "test/helloworld.go")) + return + } -func (c compile) run(name string, count int) error { // Make sure dependencies needed by go tool compile are installed to GOROOT/pkg. - out, err := exec.Command(*flagGoCmd, "build", "-i", c.dir).CombinedOutput() + out, err := exec.Command(*flagGoCmd, "build", "-i", dir).CombinedOutput() if err != nil { - return fmt.Errorf("go build -i %s: %v\n%s", c.dir, err, out) + log.Printf("go build -i %s: %v\n%s", dir, err, out) + return } // Find dir and source file list. - pkg, err := goList(c.dir) - if err != nil { - return err - } - - args := []string{"-o", "_compilebench_.o"} - args = append(args, strings.Fields(*flagCompilerFlags)...) - args = append(args, pkg.GoFiles...) - if err := runBuildCmd(name, count, pkg.Dir, compiler, args); err != nil { - return err + var pkg struct { + Dir string + GoFiles []string } - - opath := pkg.Dir + "/_compilebench_.o" - if *flagObj { - // TODO(josharian): object files are big; just read enough to find what we seek. - data, err := ioutil.ReadFile(opath) - if err != nil { - log.Print(err) - } - // Find start of export data. - i := bytes.Index(data, []byte("\n$$B\n")) + len("\n$$B\n") - // Count bytes to end of export data. - nexport := bytes.Index(data[i:], []byte("\n$$\n")) - fmt.Printf(" %d object-bytes %d export-bytes", len(data), nexport) - } - fmt.Println() - - os.Remove(opath) - return nil -} - -type link struct{ dir, flags string } - -func (link) long() bool { return false } - -func (r link) run(name string, count int) error { - if linker == "" { - // No linker. Skip the test. - return nil - } - - // Build dependencies. - out, err := exec.Command(*flagGoCmd, "build", "-i", "-o", "/dev/null", r.dir).CombinedOutput() - if err != nil { - return fmt.Errorf("go build -i %s: %v\n%s", r.dir, err, out) - } - - // Build the main package. - pkg, err := goList(r.dir) + out, err = exec.Command(*flagGoCmd, "list", "-json", dir).Output() if err != nil { - return err + log.Printf("go list -json %s: %v\n", dir, err) + return } - args := []string{"-o", "_compilebench_.o"} - args = append(args, pkg.GoFiles...) - cmd := exec.Command(compiler, args...) - cmd.Dir = pkg.Dir - cmd.Stdout = os.Stderr - cmd.Stderr = os.Stderr - err = cmd.Run() - if err != nil { - return fmt.Errorf("compiling: %v", err) + if err := json.Unmarshal(out, &pkg); err != nil { + log.Printf("go list -json %s: unmarshal: %v", dir, err) + return } - defer os.Remove(pkg.Dir + "/_compilebench_.o") - // Link the main package. - args = []string{"-o", "_compilebench_.exe"} - args = append(args, strings.Fields(*flagLinkerFlags)...) - args = append(args, strings.Fields(r.flags)...) - args = append(args, "_compilebench_.o") - if err := runBuildCmd(name, count, pkg.Dir, linker, args); err != nil { - return err + args := []string{"-o", "_compilebench_.o"} + if is6g { + *flagMemprofilerate = -1 + *flagAlloc = false + *flagCpuprofile = "" + *flagMemprofile = "" } - fmt.Println() - defer os.Remove(pkg.Dir + "/_compilebench_.exe") - - return err -} - -// runBuildCmd runs "tool args..." in dir, measures standard build -// tool metrics, and prints a benchmark line. The caller may print -// additional metrics and then must print a newline. -// -// This assumes tool accepts standard build tool flags like -// -memprofilerate, -memprofile, and -cpuprofile. -func runBuildCmd(name string, count int, dir, tool string, args []string) error { - var preArgs []string if *flagMemprofilerate >= 0 { - preArgs = append(preArgs, "-memprofilerate", fmt.Sprint(*flagMemprofilerate)) + args = append(args, "-memprofilerate", fmt.Sprint(*flagMemprofilerate)) } + args = append(args, strings.Fields(*flagCompilerFlags)...) if *flagAlloc || *flagCpuprofile != "" || *flagMemprofile != "" { if *flagAlloc || *flagMemprofile != "" { - preArgs = append(preArgs, "-memprofile", "_compilebench_.memprof") + args = append(args, "-memprofile", "_compilebench_.memprof") } if *flagCpuprofile != "" { - preArgs = append(preArgs, "-cpuprofile", "_compilebench_.cpuprof") + args = append(args, "-cpuprofile", "_compilebench_.cpuprof") } } - cmd := exec.Command(tool, append(preArgs, args...)...) - cmd.Dir = dir + args = append(args, pkg.GoFiles...) + cmd := exec.Command(compiler, args...) + cmd.Dir = pkg.Dir cmd.Stdout = os.Stderr cmd.Stderr = os.Stderr start := time.Now() - err := cmd.Run() + err = cmd.Run() if err != nil { - return err + log.Printf("%v: %v", name, err) + return } end := time.Now() - haveAllocs := false var allocs, allocbytes int64 if *flagAlloc || *flagMemprofile != "" { - out, err := ioutil.ReadFile(dir + "/_compilebench_.memprof") + out, err := ioutil.ReadFile(pkg.Dir + "/_compilebench_.memprof") if err != nil { log.Print("cannot find memory profile after compilation") } @@ -456,7 +320,6 @@ func runBuildCmd(name string, count int, dir, tool string, args []string) error if err != nil { continue } - haveAllocs = true switch f[1] { case "TotalAlloc": allocbytes = val @@ -464,24 +327,17 @@ func runBuildCmd(name string, count int, dir, tool string, args []string) error allocs = val } } - if !haveAllocs { - log.Println("missing stats in memprof (golang.org/issue/18641)") - } if *flagMemprofile != "" { - outpath := *flagMemprofile - if *flagCount != 1 { - outpath = fmt.Sprintf("%s_%d", outpath, count) - } - if err := ioutil.WriteFile(outpath, out, 0666); err != nil { + if err := ioutil.WriteFile(*flagMemprofile, out, 0666); err != nil { log.Print(err) } } - os.Remove(dir + "/_compilebench_.memprof") + os.Remove(pkg.Dir + "/_compilebench_.memprof") } if *flagCpuprofile != "" { - out, err := ioutil.ReadFile(dir + "/_compilebench_.cpuprof") + out, err := ioutil.ReadFile(pkg.Dir + "/_compilebench_.cpuprof") if err != nil { log.Print(err) } @@ -492,16 +348,31 @@ func runBuildCmd(name string, count int, dir, tool string, args []string) error if err := ioutil.WriteFile(outpath, out, 0666); err != nil { log.Print(err) } - os.Remove(dir + "/_compilebench_.cpuprof") + os.Remove(pkg.Dir + "/_compilebench_.cpuprof") } wallns := end.Sub(start).Nanoseconds() userns := cmd.ProcessState.UserTime().Nanoseconds() fmt.Printf("%s 1 %d ns/op %d user-ns/op", name, wallns, userns) - if haveAllocs { + if *flagAlloc { fmt.Printf(" %d B/op %d allocs/op", allocbytes, allocs) } - return nil + opath := pkg.Dir + "/_compilebench_.o" + if *flagObj { + // TODO(josharian): object files are big; just read enough to find what we seek. + data, err := ioutil.ReadFile(opath) + if err != nil { + log.Print(err) + } + // Find start of export data. + i := bytes.Index(data, []byte("\n$$B\n")) + len("\n$$B\n") + // Count bytes to end of export data. + nexport := bytes.Index(data[i:], []byte("\n$$\n")) + fmt.Printf(" %d object-bytes %d export-bytes", len(data), nexport) + } + fmt.Println() + + os.Remove(opath) } diff --git a/vendor/golang.org/x/tools/cmd/cover/cover_test.go b/vendor/golang.org/x/tools/cmd/cover/cover_test.go index 54c4512bff..a18778b5b4 100644 --- a/vendor/golang.org/x/tools/cmd/cover/cover_test.go +++ b/vendor/golang.org/x/tools/cmd/cover/cover_test.go @@ -16,13 +16,22 @@ import ( "os/exec" "path/filepath" "testing" - - "golang.org/x/tools/internal/testenv" ) const ( // Data directory, also the package directory for the test. testdata = "testdata" + + // Binaries we compile. + testcover = "./testcover.exe" +) + +var ( + // Files we use. + testMain = filepath.Join(testdata, "main.go") + testTest = filepath.Join(testdata, "test.go") + coverInput = filepath.Join(testdata, "test_line.go") + coverOutput = filepath.Join(testdata, "test_cover.go") ) var debug = false // Keeps the rewritten files around if set. @@ -35,36 +44,6 @@ var debug = false // Keeps the rewritten files around if set. // go run ./testdata/main.go ./testdata/test.go // func TestCover(t *testing.T) { - testenv.NeedsTool(t, "go") - - tmpdir, err := ioutil.TempDir("", "TestCover") - if err != nil { - t.Fatal(err) - } - defer func() { - if debug { - fmt.Printf("test files left in %s\n", tmpdir) - } else { - os.RemoveAll(tmpdir) - } - }() - - testcover := filepath.Join(tmpdir, "testcover.exe") - testMain := filepath.Join(tmpdir, "main.go") - testTest := filepath.Join(tmpdir, "test.go") - coverInput := filepath.Join(tmpdir, "test_line.go") - coverOutput := filepath.Join(tmpdir, "test_cover.go") - - for _, f := range []string{testMain, testTest} { - data, err := ioutil.ReadFile(filepath.Join(testdata, filepath.Base(f))) - if err != nil { - t.Fatal(err) - } - if err := ioutil.WriteFile(f, data, 0644); err != nil { - t.Fatal(err) - } - } - // Read in the test file (testTest) and write it, with LINEs specified, to coverInput. file, err := ioutil.ReadFile(testTest) if err != nil { @@ -79,10 +58,18 @@ func TestCover(t *testing.T) { t.Fatal(err) } + // defer removal of test_line.go + if !debug { + defer os.Remove(coverInput) + } + // go build -o testcover cmd := exec.Command("go", "build", "-o", testcover) run(cmd, t) + // defer removal of testcover + defer os.Remove(testcover) + // ./testcover -mode=count -var=coverTest -o ./testdata/test_cover.go testdata/test_line.go cmd = exec.Command(testcover, "-mode=count", "-var=coverTest", "-o", coverOutput, coverInput) run(cmd, t) diff --git a/vendor/golang.org/x/tools/cmd/digraph/digraph.go b/vendor/golang.org/x/tools/cmd/digraph/digraph.go index 6bbff9665a..8ef2e45ef1 100644 --- a/vendor/golang.org/x/tools/cmd/digraph/digraph.go +++ b/vendor/golang.org/x/tools/cmd/digraph/digraph.go @@ -1,85 +1,18 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -The digraph command performs queries over unlabelled directed graphs -represented in text form. It is intended to integrate nicely with -typical UNIX command pipelines. - -Usage: - - your-application | digraph [command] - -The support commands are: - - nodes - the set of all nodes - degree - the in-degree and out-degree of each node - transpose - the reverse of the input edges - preds ... - the set of immediate predecessors of the specified nodes - succs ... - the set of immediate successors of the specified nodes - forward ... - the set of nodes transitively reachable from the specified nodes - reverse ... - the set of nodes that transitively reach the specified nodes - somepath - the list of nodes on some arbitrary path from the first node to the second - allpaths - the set of nodes on all paths from the first node to the second - sccs - all strongly connected components (one per line) - scc - the set of nodes nodes strongly connected to the specified one - -Input format: - -Each line contains zero or more words. Words are separated by unquoted -whitespace; words may contain Go-style double-quoted portions, allowing spaces -and other characters to be expressed. - -Each word declares a node, and if there are more than one, an edge from the -first to each subsequent one. The graph is provided on the standard input. - -For instance, the following (acyclic) graph specifies a partial order among the -subtasks of getting dressed: - - $ cat clothes.txt - socks shoes - "boxer shorts" pants - pants belt shoes - shirt tie sweater - sweater jacket - hat - -The line "shirt tie sweater" indicates the two edges shirt -> tie and -shirt -> sweater, not shirt -> tie -> sweater. - -Example usage: - -Using digraph with existing Go tools: - - $ go mod graph | digraph nodes # Operate on the Go module graph. - $ go list -m all | digraph nodes # Operate on the Go package graph. - -Show the transitive closure of imports of the digraph tool itself: - $ go list -f '{{.ImportPath}} {{join .Imports " "}}' ... | digraph forward golang.org/x/tools/cmd/digraph - -Show which clothes (see above) must be donned before a jacket: - $ digraph reverse jacket - -*/ -package main // import "golang.org/x/tools/cmd/digraph" - +// The digraph command performs queries over unlabelled directed graphs +// represented in text form. It is intended to integrate nicely with +// typical UNIX command pipelines. +// +// Since directed graphs (import graphs, reference graphs, call graphs, +// etc) often arise during software tool development and debugging, this +// command is included in the go.tools repository. +// // TODO(adonovan): // - support input files other than stdin // - support alternative formats (AT&T GraphViz, CSV, etc), // a comment syntax, etc. // - allow queries to nest, like Blaze query language. +// +package main // import "golang.org/x/tools/cmd/digraph" import ( "bufio" @@ -95,43 +28,74 @@ import ( "unicode/utf8" ) -func usage() { - fmt.Fprintf(os.Stderr, `Usage: your-application | digraph [command] - -The support commands are: - nodes - the set of all nodes - degree - the in-degree and out-degree of each node - transpose - the reverse of the input edges - preds ... - the set of immediate predecessors of the specified nodes - succs ... - the set of immediate successors of the specified nodes - forward ... - the set of nodes transitively reachable from the specified nodes - reverse ... - the set of nodes that transitively reach the specified nodes - somepath - the list of nodes on some arbitrary path from the first node to the second - allpaths - the set of nodes on all paths from the first node to the second - sccs - all strongly connected components (one per line) - scc - the set of nodes nodes strongly connected to the specified one -`) - os.Exit(2) -} +const Usage = `digraph: queries over directed graphs in text form. + +Graph format: + + Each line contains zero or more words. Words are separated by + unquoted whitespace; words may contain Go-style double-quoted portions, + allowing spaces and other characters to be expressed. + + Each field declares a node, and if there are more than one, + an edge from the first to each subsequent one. + The graph is provided on the standard input. + + For instance, the following (acyclic) graph specifies a partial order + among the subtasks of getting dressed: + + % cat clothes.txt + socks shoes + "boxer shorts" pants + pants belt shoes + shirt tie sweater + sweater jacket + hat + + The line "shirt tie sweater" indicates the two edges shirt -> tie and + shirt -> sweater, not shirt -> tie -> sweater. + +Supported queries: + + nodes + the set of all nodes + degree + the in-degree and out-degree of each node. + preds