diff --git a/README.md b/README.md index e9ce8ead..97561ed4 100644 --- a/README.md +++ b/README.md @@ -105,14 +105,19 @@ Before you can deploy your plugin on a cluster, you must build an image and push it to an image registry. 1. Build the image: + ```sh docker build -t quay.io/my-repositroy/my-plugin:latest . ``` + 2. Run the image: + ```sh docker run -it --rm -d -p 9001:80 quay.io/my-repository/my-plugin:latest ``` + 3. Push the image: + ```sh docker push quay.io/my-repository/my-plugin:latest ``` @@ -123,29 +128,20 @@ to run in-cluster. ## Deployment on cluster -After pushing an image with your changes to a registry, you can deploy the -plugin to a cluster by instantiating the provided -[OpenShift template](template.yaml). It will run a light-weight nginx HTTP -server to serve your plugin's assets. - -```sh -oc process -f template.yaml \ - -p PLUGIN_NAME=my-plugin \ - -p NAMESPACE=my-plugin-namespace \ - -p IMAGE=quay.io/my-repository/my-plugin:latest \ - | oc create -f - -``` +A [Helm](https://helm.sh) chart is available to deploy the plugin to an OpenShift environment. + +The following Helm parameters are required: + +`plugin.image`: The location of the image containing the plugin that was previously pushed + +Additional parameters can be specified if desired. Consult the chart [values](charts/openshift-console-plugin/values.yaml) file for the full set of supported parameters. -`PLUGIN_NAME` must match the plugin name you used in the `consolePlugin` -declaration of [package.json](package.json). +### Installing the Helm Chart -Once deployed, patch the -[Console operator](https://github.com/openshift/console-operator) -config to enable the plugin. +Install the chart using the name of the plugin as the Helm release name into a new namespace or an existing namespace as specified by the `my-plugin-namespace` parameter by using the following command: -```sh -oc patch consoles.operator.openshift.io cluster \ - --patch '{ "spec": { "plugins": ["my-plugin"] } }' --type=merge +```shell +helm upgrade -i my-plugin charts/openshift-console-plugin -n my-plugin-namespace --create-namespace ``` ## Linting diff --git a/charts/openshift-console-plugin/.helmignore b/charts/openshift-console-plugin/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /dev/null +++ b/charts/openshift-console-plugin/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/openshift-console-plugin/Chart.yaml b/charts/openshift-console-plugin/Chart.yaml new file mode 100644 index 00000000..90ff8f23 --- /dev/null +++ b/charts/openshift-console-plugin/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: openshift-console-plugin +description: A Helm chart for Kubernetes +type: application +version: 0.1.0 diff --git a/charts/openshift-console-plugin/templates/_helpers.tpl b/charts/openshift-console-plugin/templates/_helpers.tpl new file mode 100644 index 00000000..4d489739 --- /dev/null +++ b/charts/openshift-console-plugin/templates/_helpers.tpl @@ -0,0 +1,72 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "openshift-console-plugin.name" -}} +{{- default (default .Chart.Name .Release.Name) .Values.plugin.name | trunc 63 | trimSuffix "-" }} +{{- end }} + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "openshift-console-plugin.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "openshift-console-plugin.labels" -}} +helm.sh/chart: {{ include "openshift-console-plugin.chart" . }} +{{ include "openshift-console-plugin.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "openshift-console-plugin.selectorLabels" -}} +app: {{ include "openshift-console-plugin.name" . }} +app.kubernetes.io/name: {{ include "openshift-console-plugin.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/part-of: {{ include "openshift-console-plugin.name" . }} +{{- end }} + +{{/* +Create the name secret containing the certificate +*/}} +{{- define "openshift-console-plugin.certificateSecret" -}} +{{ default (printf "%s-cert" (include "openshift-console-plugin.name" .)) .Values.plugin.certificateSecretName }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "openshift-console-plugin.serviceAccountName" -}} +{{- if .Values.plugin.serviceAccount.create }} +{{- default (include "openshift-console-plugin.name" .) .Values.plugin.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.plugin.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the name of the patcher +*/}} +{{- define "openshift-console-plugin.patcherName" -}} +{{- printf "%s-patcher" (include "openshift-console-plugin.name" .) }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "openshift-console-plugin.patcherServiceAccountName" -}} +{{- if .Values.plugin.patcherServiceAccount.create }} +{{- default (printf "%s-patcher" (include "openshift-console-plugin.name" .)) .Values.plugin.patcherServiceAccount.name }} +{{- else }} +{{- default "default" .Values.plugin.patcherServiceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/charts/openshift-console-plugin/templates/configmap.yaml b/charts/openshift-console-plugin/templates/configmap.yaml new file mode 100644 index 00000000..eae6a4f2 --- /dev/null +++ b/charts/openshift-console-plugin/templates/configmap.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "openshift-console-plugin.name" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} +data: + nginx.conf: | + error_log /dev/stdout info; + events {} + http { + access_log /dev/stdout; + include /etc/nginx/mime.types; + default_type application/octet-stream; + keepalive_timeout 65; + server { + listen {{ .Values.plugin.port }} ssl; + ssl_certificate /var/cert/tls.crt; + ssl_certificate_key /var/cert/tls.key; + root /usr/share/nginx/html; + } + } diff --git a/charts/openshift-console-plugin/templates/consoleplugin.yaml b/charts/openshift-console-plugin/templates/consoleplugin.yaml new file mode 100644 index 00000000..0b652286 --- /dev/null +++ b/charts/openshift-console-plugin/templates/consoleplugin.yaml @@ -0,0 +1,14 @@ +apiVersion: console.openshift.io/v1alpha1 +kind: ConsolePlugin +metadata: + name: {{ template "openshift-console-plugin.name" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} +spec: + displayName: {{ default (printf "%s Plugin" (include "openshift-console-plugin.name" .)) .Values.plugin.description }} + service: + name: {{ template "openshift-console-plugin.name" . }} + namespace: {{ .Release.Namespace }} + port: {{ .Values.plugin.port }} + basePath: {{ .Values.plugin.basePath }} \ No newline at end of file diff --git a/charts/openshift-console-plugin/templates/deployment.yaml b/charts/openshift-console-plugin/templates/deployment.yaml new file mode 100644 index 00000000..27ed97ab --- /dev/null +++ b/charts/openshift-console-plugin/templates/deployment.yaml @@ -0,0 +1,59 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "openshift-console-plugin.name" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} + app.openshift.io/runtime-namespace: {{ .Release.Namespace }} +spec: + replicas: {{ .Values.plugin.replicas }} + selector: + matchLabels: + {{- include "openshift-console-plugin.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "openshift-console-plugin.labels" . | nindent 8 }} + spec: + containers: + - name: {{ template "openshift-console-plugin.name" . }} + image: {{ required "Plugin image must be specified!" .Values.plugin.image }} + ports: + - containerPort: {{ .Values.plugin.port }} + protocol: TCP + imagePullPolicy: {{ .Values.plugin.imagePullPolicy }} + {{- if .Values.plugin.containerSecurityContext }} + securityContext: + {{ tpl (toYaml .Values.plugin.containerSecurityContext | indent 12) . }} + {{- end }} + resources: + {{- toYaml .Values.plugin.resources | nindent 12 }} + volumeMounts: + - name: {{ template "openshift-console-plugin.certificateSecret" . }} + readOnly: true + mountPath: /var/cert + - name: nginx-conf + readOnly: true + mountPath: /etc/nginx/nginx.conf + subPath: nginx.conf + volumes: + - name: {{ template "openshift-console-plugin.certificateSecret" . }} + secret: + secretName: {{ template "openshift-console-plugin.certificateSecret" . }} + defaultMode: 420 + - name: nginx-conf + configMap: + name: {{ template "openshift-console-plugin.name" . }} + defaultMode: 420 + restartPolicy: Always + dnsPolicy: ClusterFirst + {{- if .Values.plugin.podSecurityContext }} + securityContext: + {{ tpl (toYaml .Values.plugin.podSecurityContext | indent 8) . }} + {{- end }} + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 25% + maxSurge: 25% diff --git a/charts/openshift-console-plugin/templates/patch-consoles-job.yaml b/charts/openshift-console-plugin/templates/patch-consoles-job.yaml new file mode 100644 index 00000000..a79294c4 --- /dev/null +++ b/charts/openshift-console-plugin/templates/patch-consoles-job.yaml @@ -0,0 +1,41 @@ +{{- if .Values.plugin.jobs.patchConsoles.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ template "openshift-console-plugin.patcherName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} + annotations: + helm.sh/hook: post-install,post-upgrade + helm.sh/hook-delete-policy: before-hook-creation +spec: + parallelism: 1 + template: + metadata: + labels: + {{- include "openshift-console-plugin.labels" . | nindent 8 }} + spec: + restartPolicy: OnFailure + serviceAccountName: {{ template "openshift-console-plugin.patcherServiceAccountName" . }} + {{- if .Values.plugin.jobs.patchConsoles.podSecurityContext }} + securityContext: + {{ tpl (toYaml .Values.plugin.jobs.patchConsoles.podSecurityContext | indent 8) . }} + {{- end }} + terminationGracePeriodSeconds: 400 + dnsPolicy: ClusterFirst + containers: + - name: {{ template "openshift-console-plugin.patcherName" . }} + image: {{ required "Patcher image must be specified!" .Values.plugin.jobs.patchConsoles.image }} + {{- if .Values.plugin.jobs.patchConsoles.containerSecurityContext }} + securityContext: + {{ tpl (toYaml .Values.plugin.jobs.patchConsoles.containerSecurityContext | indent 8) . }} + {{- end }} + resources: + {{- toYaml .Values.plugin.jobs.patchConsoles.resources | nindent 12 }} + command: + - /bin/bash + - -c + - | + oc patch consoles.operator.openshift.io cluster --patch '{ "spec": { "plugins": ["{{ template "openshift-console-plugin.name" . }}"] } }' --type=merge +{{- end }} \ No newline at end of file diff --git a/charts/openshift-console-plugin/templates/patcher-clusterrole.yaml b/charts/openshift-console-plugin/templates/patcher-clusterrole.yaml new file mode 100644 index 00000000..31c050a5 --- /dev/null +++ b/charts/openshift-console-plugin/templates/patcher-clusterrole.yaml @@ -0,0 +1,13 @@ +{{- if .Values.plugin.jobs.patchConsoles.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "openshift-console-plugin.patcherName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} +rules: + - apiGroups: ["operator.openshift.io"] + resources: ["consoles"] + verbs: ["get","list","patch", "update"] +{{- end }} \ No newline at end of file diff --git a/charts/openshift-console-plugin/templates/patcher-clusterrolebinding.yaml b/charts/openshift-console-plugin/templates/patcher-clusterrolebinding.yaml new file mode 100644 index 00000000..d93b8721 --- /dev/null +++ b/charts/openshift-console-plugin/templates/patcher-clusterrolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.plugin.jobs.patchConsoles.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "openshift-console-plugin.patcherName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "openshift-console-plugin.patcherName" . }} +subjects: + - kind: ServiceAccount + name: {{ template "openshift-console-plugin.patcherServiceAccountName" . }} + namespace: {{ .Release.Namespace }} +{{- end }} \ No newline at end of file diff --git a/charts/openshift-console-plugin/templates/patcher-serviceaccount.yaml b/charts/openshift-console-plugin/templates/patcher-serviceaccount.yaml new file mode 100644 index 00000000..4af6a6b9 --- /dev/null +++ b/charts/openshift-console-plugin/templates/patcher-serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if and (.Values.plugin.patcherServiceAccount.create) (.Values.plugin.jobs.patchConsoles.enabled) -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "openshift-console-plugin.patcherServiceAccountName" . }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.patcherServiceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/openshift-console-plugin/templates/service.yaml b/charts/openshift-console-plugin/templates/service.yaml new file mode 100644 index 00000000..cb6c9bfc --- /dev/null +++ b/charts/openshift-console-plugin/templates/service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + {{- if not .Values.certificateSecretName }} + annotations: + service.alpha.openshift.io/serving-cert-secret-name: {{ template "openshift-console-plugin.certificateSecret" . }} + {{- end }} + name: {{ template "openshift-console-plugin.name" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} +spec: + ports: + - name: {{ .Values.plugin.port }}-tcp + protocol: TCP + port: {{ .Values.plugin.port }} + targetPort: {{ .Values.plugin.port }} + selector: + {{- include "openshift-console-plugin.selectorLabels" . | nindent 4 }} + type: ClusterIP + sessionAffinity: None diff --git a/charts/openshift-console-plugin/templates/serviceaccount.yaml b/charts/openshift-console-plugin/templates/serviceaccount.yaml new file mode 100644 index 00000000..5c3dffe4 --- /dev/null +++ b/charts/openshift-console-plugin/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.plugin.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "openshift-console-plugin.serviceAccountName" . }} + labels: + {{- include "openshift-console-plugin.labels" . | nindent 4 }} + {{- with .Values.plugin.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/openshift-console-plugin/values.yaml b/charts/openshift-console-plugin/values.yaml new file mode 100644 index 00000000..fc60104e --- /dev/null +++ b/charts/openshift-console-plugin/values.yaml @@ -0,0 +1,34 @@ +--- +plugin: + name: "" + description: "" + image: "" + imagePullPolicy: IfNotPresent + replicas: 2 + port: 9443 + podSecurityContext: {} + containerSecurityContext: {} + resources: + requests: + cpu: 10m + memory: 50Mi + basePath: / + certificateSecretName: "" + serviceAccount: + create: true + annotations: {} + name: "" + patcherServiceAccount: + create: true + annotations: {} + name: "" + jobs: + patchConsoles: + enabled: true + image: "registry.redhat.io/openshift4/ose-tools-rhel8@sha256:e44074f21e0cca6464e50cb6ff934747e0bd11162ea01d522433a1a1ae116103" + podSecurityContext: {} + containerSecurityContext: {} + resources: + requests: + cpu: 10m + memory: 50Mi diff --git a/ct.yaml b/ct.yaml new file mode 100644 index 00000000..f178aec1 --- /dev/null +++ b/ct.yaml @@ -0,0 +1,5 @@ +chart-dirs: + - charts +validate-maintainers: false +remote: origin +target-branch: main diff --git a/template.yaml b/template.yaml deleted file mode 100644 index d525a487..00000000 --- a/template.yaml +++ /dev/null @@ -1,158 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -metadata: - name: console-plugin-template - annotations: - openshift.io/display-name: OpenShift Console Plugin Template - openshift.io/documentation-url: "https://github.com/spadgett/console-plugin-template" - description: >- - nginx HTTP server for an OpenShift console plugin creating using the - template at https://github.com/spadgett/console-plugin-template - iconClass: icon-nginx - tags: openshift,console,plugin,nginx -parameters: -- description: Name of your plugin. This name must match the name in the consolePlugin declaration in package.json. - name: PLUGIN_NAME - value: console-plugin-template - required: true -- description: Namespace for your plugin. The namespace will be created by the template. - name: NAMESPACE - value: console-plugin-template - required: true -- description: Container image of the plugin. - name: IMAGE - value: quay.io/spadgett/console-plugin-template:latest - required: true -message: >- - To enable the plugin on the cluster, run the following command: - - oc patch consoles.operator.openshift.io cluster --patch '{ "spec": { "plugins": ["${PLUGIN_NAME}"] } }' --type=merge - - For more information about using this template, see https://github.com/spadgett/console-plugin-template -objects: - - apiVersion: v1 - kind: Namespace - metadata: - name: '${NAMESPACE}' - - apiVersion: apps/v1 - kind: Deployment - metadata: - name: '${PLUGIN_NAME}' - namespace: '${NAMESPACE}' - labels: - app: '${PLUGIN_NAME}' - app.kubernetes.io/component: '${PLUGIN_NAME}' - app.kubernetes.io/instance: '${PLUGIN_NAME}' - app.kubernetes.io/part-of: '${PLUGIN_NAME}' - app.openshift.io/runtime-namespace: '${NAMESPACE}' - spec: - replicas: 2 - selector: - matchLabels: - app: '${PLUGIN_NAME}' - template: - metadata: - labels: - app: '${PLUGIN_NAME}' - spec: - containers: - - name: '${PLUGIN_NAME}' - image: '${IMAGE}' - ports: - - containerPort: 9443 - protocol: TCP - imagePullPolicy: Always - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - resources: - requests: - cpu: 10m - memory: 50Mi - volumeMounts: - - name: plugin-serving-cert - readOnly: true - mountPath: /var/serving-cert - - name: nginx-conf - readOnly: true - mountPath: /etc/nginx/nginx.conf - subPath: nginx.conf - volumes: - - name: plugin-serving-cert - secret: - secretName: plugin-serving-cert - defaultMode: 420 - - name: nginx-conf - configMap: - name: nginx-conf - defaultMode: 420 - restartPolicy: Always - dnsPolicy: ClusterFirst - securityContext: - runAsNonRoot: true - seccompProfile: - type: RuntimeDefault - strategy: - type: RollingUpdate - rollingUpdate: - maxUnavailable: 25% - maxSurge: 25% - - apiVersion: v1 - kind: ConfigMap - metadata: - name: nginx-conf - namespace: '${NAMESPACE}' - labels: - app: '${PLUGIN_NAME}' - app.kubernetes.io/part-of: '${PLUGIN_NAME}' - data: - nginx.conf: | - error_log /dev/stdout info; - events {} - http { - access_log /dev/stdout; - include /etc/nginx/mime.types; - default_type application/octet-stream; - keepalive_timeout 65; - server { - listen 9443 ssl; - ssl_certificate /var/serving-cert/tls.crt; - ssl_certificate_key /var/serving-cert/tls.key; - root /usr/share/nginx/html; - } - } - - apiVersion: v1 - kind: Service - metadata: - annotations: - service.alpha.openshift.io/serving-cert-secret-name: plugin-serving-cert - name: '${PLUGIN_NAME}' - namespace: '${NAMESPACE}' - labels: - app: '${PLUGIN_NAME}' - app.kubernetes.io/component: '${PLUGIN_NAME}' - app.kubernetes.io/instance: '${PLUGIN_NAME}' - app.kubernetes.io/part-of: '${PLUGIN_NAME}' - spec: - ports: - - name: 9443-tcp - protocol: TCP - port: 9443 - targetPort: 9443 - selector: - app: '${PLUGIN_NAME}' - type: ClusterIP - sessionAffinity: None - - apiVersion: console.openshift.io/v1alpha1 - kind: ConsolePlugin - metadata: - name: '${PLUGIN_NAME}' - spec: - displayName: 'Console Plugin Template' - service: - name: '${PLUGIN_NAME}' - namespace: '${NAMESPACE}' - port: 9443 - basePath: '/'