diff --git a/Makefile b/Makefile index e0ed03f4..c8cc0449 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +OLD_TAG = 0.0.3 TAG = 0.0.4 IMAGE = nginx-ingress-operator @@ -21,7 +22,7 @@ lint: golangci-lint run generate-metadata: generate-crds - operator-sdk generate csv --csv-version $(TAG) + operator-sdk generate csv --csv-version=$(TAG) --from-version=$(OLD_TAG) --make-manifests=false echo "Metadata generated, please make sure you add/update fields in nginx-ingress-operator.v$(TAG).clusterserviceversion.yaml" generate-bundle: diff --git a/README.md b/README.md index 1f66f28c..4990a937 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,13 @@ It is possible to run the operator in your local machine. This is useful for tes ``` kubectl apply -f deploy/crds/k8s.nginx.org_nginxingresscontrollers_crd.yaml ``` +1. Apply the NGINX Ingress Controller CRDs: + ``` + kubectl apply -f build/kic_crds + ``` 1. Run `make run-local`. -The operator will run in your local machine but will be communicating with the cluster. +The operator will run in your local machine but will be communicating with the cluster. The operator will only watch the `default` namespace when deployed locally. ### Update CRD diff --git a/build/Dockerfile b/build/Dockerfile index b4119354..85ed63dc 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -11,6 +11,7 @@ COPY build/bin /usr/local/bin RUN /usr/local/bin/user_setup COPY LICENSE /licenses/ +COPY build/kic_crds /kic_crds ENTRYPOINT ["/usr/local/bin/entrypoint"] diff --git a/build/kic_crds/gc-definition.yaml b/build/kic_crds/gc-definition.yaml new file mode 100644 index 00000000..7d93d8ad --- /dev/null +++ b/build/kic_crds/gc-definition.yaml @@ -0,0 +1,52 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: globalconfigurations.k8s.nginx.org +spec: + group: k8s.nginx.org + versions: + - name: v1alpha1 + served: true + storage: true + scope: Namespaced + names: + plural: globalconfigurations + singular: globalconfiguration + kind: GlobalConfiguration + shortNames: + - gc + preserveUnknownFields: false + validation: + openAPIV3Schema: + description: GlobalConfiguration defines the GlobalConfiguration resource. + 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: GlobalConfigurationSpec is the spec of the GlobalConfiguration + resource. + type: object + properties: + listeners: + type: array + items: + description: Listener defines a listener. + type: object + properties: + name: + type: string + port: + type: integer + protocol: + type: string \ No newline at end of file diff --git a/build/kic_crds/policy-definition.yaml b/build/kic_crds/policy-definition.yaml new file mode 100644 index 00000000..90b1b0de --- /dev/null +++ b/build/kic_crds/policy-definition.yaml @@ -0,0 +1,56 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: policies.k8s.nginx.org +spec: + group: k8s.nginx.org + versions: + - name: v1alpha1 + served: true + storage: true + scope: Namespaced + names: + plural: policies + singular: policy + kind: Policy + shortNames: + - pol + preserveUnknownFields: false + validation: + openAPIV3Schema: + description: Policy defines a Policy for VirtualServer and VirtualServerRoute + resources. + 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: 'PolicySpec is the spec of the Policy resource. The spec includes + multiple fields, where each field represents a different policy. Note: + currently we have only one policy -- AccessControl, but we will support + more in the future. Only one policy (field) is allowed.' + type: object + properties: + accessControl: + description: AccessControl defines an access policy based on the source + IP of a request. + type: object + properties: + allow: + type: array + items: + type: string + deny: + type: array + items: + type: string \ No newline at end of file diff --git a/build/kic_crds/ts-definition.yaml b/build/kic_crds/ts-definition.yaml new file mode 100644 index 00000000..e2068131 --- /dev/null +++ b/build/kic_crds/ts-definition.yaml @@ -0,0 +1,75 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: transportservers.k8s.nginx.org +spec: + group: k8s.nginx.org + versions: + - name: v1alpha1 + served: true + storage: true + scope: Namespaced + names: + plural: transportservers + singular: transportserver + kind: TransportServer + shortNames: + - ts + preserveUnknownFields: false + validation: + openAPIV3Schema: + description: TransportServer defines the TransportServer resource. + 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: TransportServerSpec is the spec of the TransportServer resource. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + host: + type: string + listener: + description: TransportServerListener defines a listener for a TransportServer. + type: object + properties: + name: + type: string + protocol: + type: string + upstreamParameters: + description: UpstreamParameters defines parameters for an upstream. + type: object + properties: + udpRequests: + type: integer + udpResponses: + type: integer + upstreams: + type: array + items: + description: Upstream defines an upstream. + type: object + properties: + name: + type: string + port: + type: integer + service: + type: string \ No newline at end of file diff --git a/build/kic_crds/vs-definition.yaml b/build/kic_crds/vs-definition.yaml new file mode 100644 index 00000000..2a6a41b4 --- /dev/null +++ b/build/kic_crds/vs-definition.yaml @@ -0,0 +1,664 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: virtualservers.k8s.nginx.org +spec: + group: k8s.nginx.org + versions: + - name: v1 + served: true + storage: true + scope: Namespaced + subresources: + status: {} + names: + kind: VirtualServer + plural: virtualservers + singular: virtualserver + shortNames: + - vs + preserveUnknownFields: false + additionalPrinterColumns: + - name: State + type: string + description: Current state of the VirtualServer. If the resource has a valid status, + it means it has been validated and accepted by the Ingress Controller. + JSONPath: .status.state + - name: Host + type: string + JSONPath: .spec.host + - name: IP + type: string + JSONPath: .status.externalEndpoints[*].ip + - name: Ports + type: string + JSONPath: .status.externalEndpoints[*].ports + - name: Age + type: date + JSONPath: .metadata.creationTimestamp + validation: + openAPIV3Schema: + description: VirtualServer defines the VirtualServer resource. + 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: VirtualServerSpec is the spec of the VirtualServer resource. + type: object + properties: + host: + type: string + http-snippets: + type: string + ingressClassName: + type: string + policies: + type: array + items: + description: PolicyReference references a policy by name and an optional + namespace. + type: object + properties: + name: + type: string + namespace: + type: string + routes: + type: array + items: + description: Route defines a route. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the request headers + manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the response + headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP Header with + an optional Always field to use with the add_header + NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect in an Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + errorPages: + type: array + items: + description: ErrorPage defines an ErrorPage in a Route. + type: object + properties: + codes: + type: array + items: + type: integer + redirect: + description: ErrorPageRedirect defines a redirect for an + ErrorPage. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ErrorPageReturn defines a return for an ErrorPage. + type: object + properties: + body: + type: string + code: + type: integer + headers: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + type: + type: string + location-snippets: + type: string + matches: + type: array + items: + description: Match defines a match. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the request + headers manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the response + headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP Header + with an optional Always field to use with + the add_header NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect in an + Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + conditions: + type: array + items: + description: Condition defines a condition in a MatchRule. + type: object + properties: + argument: + type: string + cookie: + type: string + header: + type: string + value: + type: string + variable: + type: string + splits: + type: array + items: + description: Split defines a split. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an + Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the + request headers manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP + Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the + response headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP + Header with an optional Always field + to use with the add_header NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect + in an Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in + an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + weight: + type: integer + path: + type: string + route: + type: string + splits: + type: array + items: + description: Split defines a split. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the request + headers manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the response + headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP Header + with an optional Always field to use with + the add_header NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect in an + Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + weight: + type: integer + server-snippets: + type: string + tls: + description: TLS defines TLS configuration for a VirtualServer. + type: object + properties: + redirect: + description: TLSRedirect defines a redirect for a TLS. + type: object + properties: + basedOn: + type: string + code: + type: integer + enable: + type: boolean + secret: + type: string + upstreams: + type: array + items: + description: Upstream defines an upstream. + type: object + properties: + buffer-size: + type: string + buffering: + type: boolean + buffers: + description: UpstreamBuffers defines Buffer Configuration for + an Upstream. + type: object + properties: + number: + type: integer + size: + type: string + client-max-body-size: + type: string + connect-timeout: + type: string + fail-timeout: + type: string + healthCheck: + description: HealthCheck defines the parameters for active Upstream + HealthChecks. + type: object + properties: + connect-timeout: + type: string + enable: + type: boolean + fails: + type: integer + headers: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + interval: + type: string + jitter: + type: string + passes: + type: integer + path: + type: string + port: + type: integer + read-timeout: + type: string + send-timeout: + type: string + statusMatch: + type: string + tls: + description: UpstreamTLS defines a TLS configuration for an + Upstream. + type: object + properties: + enable: + type: boolean + keepalive: + type: integer + lb-method: + type: string + max-conns: + type: integer + max-fails: + type: integer + name: + type: string + next-upstream: + type: string + next-upstream-timeout: + type: string + next-upstream-tries: + type: integer + port: + type: integer + queue: + description: UpstreamQueue defines Queue Configuration for an + Upstream. + type: object + properties: + size: + type: integer + timeout: + type: string + read-timeout: + type: string + send-timeout: + type: string + service: + type: string + sessionCookie: + description: SessionCookie defines the parameters for session + persistence. + type: object + properties: + domain: + type: string + enable: + type: boolean + expires: + type: string + httpOnly: + type: boolean + name: + type: string + path: + type: string + secure: + type: boolean + slow-start: + type: string + subselector: + type: object + additionalProperties: + type: string + tls: + description: UpstreamTLS defines a TLS configuration for an Upstream. + type: object + properties: + enable: + type: boolean + status: + description: VirtualServerStatus defines the status for the VirtualServer + resource. + type: object + properties: + externalEndpoints: + type: array + items: + description: ExternalEndpoint defines the IP and ports used to connect + to this resource. + type: object + properties: + ip: + type: string + ports: + type: string + message: + type: string + reason: + type: string + state: + type: string \ No newline at end of file diff --git a/build/kic_crds/vsr-definition.yaml b/build/kic_crds/vsr-definition.yaml new file mode 100644 index 00000000..5def970b --- /dev/null +++ b/build/kic_crds/vsr-definition.yaml @@ -0,0 +1,633 @@ +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: virtualserverroutes.k8s.nginx.org +spec: + group: k8s.nginx.org + versions: + - name: v1 + served: true + storage: true + scope: Namespaced + subresources: + status: {} + names: + kind: VirtualServerRoute + plural: virtualserverroutes + singular: virtualserverroute + shortNames: + - vsr + preserveUnknownFields: false + additionalPrinterColumns: + - name: State + type: string + description: Current state of the VirtualServerRoute. If the resource has a valid + status, it means it has been validated and accepted by the Ingress Controller. + JSONPath: .status.state + - name: Host + type: string + JSONPath: .spec.host + - name: IP + type: string + JSONPath: .status.externalEndpoints[*].ip + - name: Ports + type: string + JSONPath: .status.externalEndpoints[*].ports + - name: Age + type: date + JSONPath: .metadata.creationTimestamp + validation: + openAPIV3Schema: + 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: + type: object + properties: + host: + type: string + ingressClassName: + type: string + subroutes: + type: array + items: + description: Route defines a route. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the request headers + manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the response + headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP Header with + an optional Always field to use with the add_header + NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect in an Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + errorPages: + type: array + items: + description: ErrorPage defines an ErrorPage in a Route. + type: object + properties: + codes: + type: array + items: + type: integer + redirect: + description: ErrorPageRedirect defines a redirect for an + ErrorPage. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ErrorPageReturn defines a return for an ErrorPage. + type: object + properties: + body: + type: string + code: + type: integer + headers: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + type: + type: string + location-snippets: + type: string + matches: + type: array + items: + description: Match defines a match. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the request + headers manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the response + headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP Header + with an optional Always field to use with + the add_header NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect in an + Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + conditions: + type: array + items: + description: Condition defines a condition in a MatchRule. + type: object + properties: + argument: + type: string + cookie: + type: string + header: + type: string + value: + type: string + variable: + type: string + splits: + type: array + items: + description: Split defines a split. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an + Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the + request headers manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP + Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the + response headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP + Header with an optional Always field + to use with the add_header NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect + in an Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in + an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + weight: + type: integer + path: + type: string + route: + type: string + splits: + type: array + items: + description: Split defines a split. + type: object + properties: + action: + description: Action defines an action. + type: object + properties: + pass: + type: string + proxy: + description: ActionProxy defines a proxy in an Action. + type: object + properties: + requestHeaders: + description: ProxyRequestHeaders defines the request + headers manipulation in an ActionProxy. + type: object + properties: + pass: + type: boolean + set: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + responseHeaders: + description: ProxyRequestHeaders defines the response + headers manipulation in an ActionProxy. + type: object + properties: + add: + type: array + items: + description: Header defines an HTTP Header + with an optional Always field to use with + the add_header NGINX directive. + type: object + properties: + always: + type: boolean + name: + type: string + value: + type: string + hide: + type: array + items: + type: string + ignore: + type: array + items: + type: string + pass: + type: array + items: + type: string + rewritePath: + type: string + upstream: + type: string + redirect: + description: ActionRedirect defines a redirect in an + Action. + type: object + properties: + code: + type: integer + url: + type: string + return: + description: ActionReturn defines a return in an Action. + type: object + properties: + body: + type: string + code: + type: integer + type: + type: string + weight: + type: integer + upstreams: + type: array + items: + description: Upstream defines an upstream. + type: object + properties: + buffer-size: + type: string + buffering: + type: boolean + buffers: + description: UpstreamBuffers defines Buffer Configuration for + an Upstream. + type: object + properties: + number: + type: integer + size: + type: string + client-max-body-size: + type: string + connect-timeout: + type: string + fail-timeout: + type: string + healthCheck: + description: HealthCheck defines the parameters for active Upstream + HealthChecks. + type: object + properties: + connect-timeout: + type: string + enable: + type: boolean + fails: + type: integer + headers: + type: array + items: + description: Header defines an HTTP Header. + type: object + properties: + name: + type: string + value: + type: string + interval: + type: string + jitter: + type: string + passes: + type: integer + path: + type: string + port: + type: integer + read-timeout: + type: string + send-timeout: + type: string + statusMatch: + type: string + tls: + description: UpstreamTLS defines a TLS configuration for an + Upstream. + type: object + properties: + enable: + type: boolean + keepalive: + type: integer + lb-method: + type: string + max-conns: + type: integer + max-fails: + type: integer + name: + type: string + next-upstream: + type: string + next-upstream-timeout: + type: string + next-upstream-tries: + type: integer + port: + type: integer + queue: + description: UpstreamQueue defines Queue Configuration for an + Upstream. + type: object + properties: + size: + type: integer + timeout: + type: string + read-timeout: + type: string + send-timeout: + type: string + service: + type: string + sessionCookie: + description: SessionCookie defines the parameters for session + persistence. + type: object + properties: + domain: + type: string + enable: + type: boolean + expires: + type: string + httpOnly: + type: boolean + name: + type: string + path: + type: string + secure: + type: boolean + slow-start: + type: string + subselector: + type: object + additionalProperties: + type: string + tls: + description: UpstreamTLS defines a TLS configuration for an Upstream. + type: object + properties: + enable: + type: boolean + status: + description: VirtualServerRouteStatus defines the status for the VirtualServerRoute + resource. + type: object + properties: + externalEndpoints: + type: array + items: + description: ExternalEndpoint defines the IP and ports used to connect + to this resource. + type: object + properties: + ip: + type: string + ports: + type: string + message: + type: string + reason: + type: string + referencedBy: + type: string + state: + type: string \ No newline at end of file diff --git a/deploy/role.yaml b/deploy/role.yaml index 2bd4876b..71da0321 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -102,6 +102,7 @@ rules: verbs: - create - delete + - update - get - apiGroups: - extensions diff --git a/pkg/controller/nginxingresscontroller/crds.go b/pkg/controller/nginxingresscontroller/crds.go index 1d41a95b..832ba5b4 100644 --- a/pkg/controller/nginxingresscontroller/crds.go +++ b/pkg/controller/nginxingresscontroller/crds.go @@ -1,106 +1,59 @@ package nginxingresscontroller import ( + "fmt" + "io/ioutil" + "os" + "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/yaml" ) -func vsForNginxIngressController() *v1beta1.CustomResourceDefinition { - return &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "virtualservers.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "virtualservers", - Singular: "virtualserver", - ShortNames: []string{"vs"}, - Kind: "VirtualServer", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1", - Served: true, - Storage: true, - }, - }, - }, +const crdsPath = "/kic_crds" +const decoderBufferSize = 100 + +func getCRDsManifests() ([]string, error) { + files, err := ioutil.ReadDir(crdsPath) + if err != nil { + return nil, err } -} -func vsrForNginxIngressController() *v1beta1.CustomResourceDefinition { - return &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "virtualserverroutes.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "virtualserverroutes", - Singular: "virtualserveroute", - ShortNames: []string{"vsr"}, - Kind: "VirtualServerRoute", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1", - Served: true, - Storage: true, - }, - }, - }, + var manifests []string + for _, f := range files { + manifests = append(manifests, fmt.Sprintf("%v/%v", crdsPath, f.Name())) } + + return manifests, nil } -func gcForNginxIngressController() *v1beta1.CustomResourceDefinition { - return &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "globalconfigurations.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "globalconfigurations", - Singular: "globalconfiguration", - ShortNames: []string{"gc"}, - Kind: "GlobalConfiguration", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1alpha1", - Served: true, - Storage: true, - }, - }, - }, +func kicCRDs() ([]*v1beta1.CustomResourceDefinition, error) { + manifests, err := getCRDsManifests() + if err != nil { + return nil, err } -} -func tsForNginxIngressController() *v1beta1.CustomResourceDefinition { - return &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "transportservers.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "transportservers", - Singular: "transportserver", - ShortNames: []string{"ts"}, - Kind: "TransportServer", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1alpha1", - Served: true, - Storage: true, - }, - }, - }, + var crds []*v1beta1.CustomResourceDefinition + for _, path := range manifests { + f, err := os.Open(path) + if err != nil { + return nil, fmt.Errorf("failed to open the CRD manifest %v: %v", path, err) + } + + var crd v1beta1.CustomResourceDefinition + + err = yaml.NewYAMLOrJSONDecoder(f, decoderBufferSize).Decode(&crd) + + if err != nil { + return nil, fmt.Errorf("failed to parse the CRD manifest %v: %v", path, err) + } + + err = f.Close() + if err != nil { + return nil, fmt.Errorf("failed to close the CRD manifest %v: %v", path, err) + } + + crds = append(crds, &crd) } + + return crds, nil } diff --git a/pkg/controller/nginxingresscontroller/crds_test.go b/pkg/controller/nginxingresscontroller/crds_test.go deleted file mode 100644 index 8ec71431..00000000 --- a/pkg/controller/nginxingresscontroller/crds_test.go +++ /dev/null @@ -1,129 +0,0 @@ -package nginxingresscontroller - -import ( - "reflect" - "testing" - - "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestVsForNginxIngressController(t *testing.T) { - expected := &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "virtualservers.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "virtualservers", - Singular: "virtualserver", - ShortNames: []string{"vs"}, - Kind: "VirtualServer", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1", - Served: true, - Storage: true, - }, - }, - }, - } - - result := vsForNginxIngressController() - if !reflect.DeepEqual(result, expected) { - t.Errorf("vsForNginxIngressController() returned %+v but expected %+v", result, expected) - } -} - -func TestVsrForNginxIngressController(t *testing.T) { - expected := &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "virtualserverroutes.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "virtualserverroutes", - Singular: "virtualserveroute", - ShortNames: []string{"vsr"}, - Kind: "VirtualServerRoute", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1", - Served: true, - Storage: true, - }, - }, - }, - } - - result := vsrForNginxIngressController() - if !reflect.DeepEqual(result, expected) { - t.Errorf("vsrForNginxIngressController() returned %+v but expected %+v", result, expected) - } -} - -func TestGcForNginxIngressController(t *testing.T) { - expected := &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "globalconfigurations.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "globalconfigurations", - Singular: "globalconfiguration", - ShortNames: []string{"gc"}, - Kind: "GlobalConfiguration", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1alpha1", - Served: true, - Storage: true, - }, - }, - }, - } - - result := gcForNginxIngressController() - if !reflect.DeepEqual(result, expected) { - t.Errorf("gcForNginxIngressController() returned %+v but expected %+v", result, expected) - } -} - -func TestTsForNginxIngressController(t *testing.T) { - expected := &v1beta1.CustomResourceDefinition{ - ObjectMeta: v1.ObjectMeta{ - Name: "transportservers.k8s.nginx.org", - }, - Spec: v1beta1.CustomResourceDefinitionSpec{ - Group: "k8s.nginx.org", - Names: v1beta1.CustomResourceDefinitionNames{ - Plural: "transportservers", - Singular: "transportserver", - ShortNames: []string{"ts"}, - Kind: "TransportServer", - }, - Scope: "Namespaced", - Versions: []v1beta1.CustomResourceDefinitionVersion{ - { - Name: "v1alpha1", - Served: true, - Storage: true, - }, - }, - }, - } - - result := tsForNginxIngressController() - if !reflect.DeepEqual(result, expected) { - t.Errorf("tsForNginxIngressController() returned %+v but expected %+v", result, expected) - } -} diff --git a/pkg/controller/nginxingresscontroller/nginxingresscontroller_controller.go b/pkg/controller/nginxingresscontroller/nginxingresscontroller_controller.go index 9a496ae1..e4c1106e 100644 --- a/pkg/controller/nginxingresscontroller/nginxingresscontroller_controller.go +++ b/pkg/controller/nginxingresscontroller/nginxingresscontroller_controller.go @@ -2,11 +2,13 @@ package nginxingresscontroller import ( "context" + commonerrors "errors" "fmt" "strings" "github.com/go-logr/logr" k8sv1alpha1 "github.com/nginxinc/nginx-ingress-operator/pkg/apis/k8s/v1alpha1" + "github.com/operator-framework/operator-sdk/pkg/k8sutil" appsv1 "k8s.io/api/apps/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -49,6 +51,66 @@ func newReconciler(mgr manager.Manager, sccAPIExists bool) reconcile.Reconciler return &ReconcileNginxIngressController{client: mgr.GetClient(), scheme: mgr.GetScheme(), sccAPIExists: sccAPIExists} } +// isLocal returns true if the Operator is running locally and false if running inside a cluster +func isLocal() bool { + _, err := k8sutil.GetOperatorNamespace() + if err != nil { + if commonerrors.Is(err, k8sutil.ErrRunLocal) { + return true + } + } + + return false +} + +func createKICCustomResourceDefinitions(mgr manager.Manager) error { + reqLogger := log.WithValues("Request.Namespace", "", "Request.Name", "nginxingresscontroller-controller") + + if isLocal() { + reqLogger.Info("Skipping KIC CRDs creation; not running in a cluster") + return nil + } + + // Create CRDs with a different client (apiextensions) + apixClient, err := apixv1beta1client.NewForConfig(mgr.GetConfig()) + if err != nil { + reqLogger.Error(err, "unable to create client for CRD registration") + return err + } + + crds, err := kicCRDs() + + if err != nil { + return err + } + + crdsClient := apixClient.CustomResourceDefinitions() + for _, crd := range crds { + oldCRD, err := crdsClient.Get(context.TODO(), crd.Name, metav1.GetOptions{}) + if err != nil { + if errors.IsNotFound(err) { + reqLogger.Info(fmt.Sprintf("no previous CRD %v found, creating a new one.", crd.Name)) + _, err = crdsClient.Create(context.TODO(), crd, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("error creating CustomResourceDefinition %v: %v", crd.Name, err) + } + } else { + return fmt.Errorf("error getting CustomResourceDefinition %v: %v", crd.Name, err) + } + } else { + // Update CRDs if they already exist + reqLogger.Info(fmt.Sprintf("previous CustomResourceDefinition %v found, updating.", crd.Name)) + oldCRD.Spec = crd.Spec + _, err = crdsClient.Update(context.TODO(), oldCRD, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("error updating CustomResourceDefinition %v: %v", crd.Name, err) + } + } + } + + return nil +} + // create common resources shared by all the Ingress Controllers func createCommonResources(mgr manager.Manager, sccAPIExists bool) error { reqLogger := log.WithValues("Request.Namespace", "", "Request.Name", "nginxingresscontroller-controller") @@ -92,45 +154,9 @@ func createCommonResources(mgr manager.Manager, sccAPIExists bool) error { return fmt.Errorf("error creating ClusterRoleBinding: %v", err) } - // Create CRDs with a different client (apiextensions) - apixClient, err := apixv1beta1client.NewForConfig(mgr.GetConfig()) + err = createKICCustomResourceDefinitions(mgr) if err != nil { - reqLogger.Error(err, "unable to create client for CRD registration") - return err - } - - crdsClient := apixClient.CustomResourceDefinitions() - vs := vsForNginxIngressController() - - _, err = crdsClient.Create(context.TODO(), vs, metav1.CreateOptions{}) - if err != nil && errors.IsAlreadyExists(err) { - reqLogger.Info("VirtualServer CRD already present, skipping creation.") - } else if err != nil { - return err - } - - vsr := vsrForNginxIngressController() - _, err = crdsClient.Create(context.TODO(), vsr, metav1.CreateOptions{}) - if err != nil && errors.IsAlreadyExists(err) { - reqLogger.Info("VirtualServerRoute CRD already present, skipping creation.") - } else if err != nil { - return err - } - - gc := gcForNginxIngressController() - _, err = crdsClient.Create(context.TODO(), gc, metav1.CreateOptions{}) - if err != nil && errors.IsAlreadyExists(err) { - reqLogger.Info("GlobalConfiguration CRD already present, skipping creation.") - } else if err != nil { - return err - } - - ts := tsForNginxIngressController() - _, err = crdsClient.Create(context.TODO(), ts, metav1.CreateOptions{}) - if err != nil && errors.IsAlreadyExists(err) { - reqLogger.Info("TransportServer CRD already present, skipping creation.") - } else if err != nil { - return err + return fmt.Errorf("error creating KIC CRDs: %v", err) } if sccAPIExists {