From ae968d44dfcae5d7891043342b5adeb1d02641a1 Mon Sep 17 00:00:00 2001 From: Marc Sluiter Date: Tue, 19 Feb 2019 13:44:20 +0100 Subject: [PATCH] Added OLM and Marketplace manifests For doing that without manifest duplication, the operator RBAC and deployment manifests are generated now too. Signed-off-by: Marc Sluiter --- .travis.yml | 1 + Makefile | 12 +- assets/kubevirt_logo.png | Bin 0 -> 11917 bytes docs/devel/olm-integration.md | 151 +++++++ hack/build-manifests.sh | 15 +- hack/builder/Dockerfile | 6 +- hack/builder/build.sh | 4 +- hack/builder/publish.sh | 11 +- hack/builder/version.sh | 1 + hack/config-default.sh | 6 + hack/config.sh | 4 +- hack/generate.sh | 5 +- hack/kubevirt-builder/Dockerfile | 4 +- hack/olm.sh | 70 ++++ .../rbac-cluster.authorization.k8s.yaml.in | 135 ++++++ ...> rbac-kubevirt.authorization.k8s.yaml.in} | 135 ------ .../rbac-operator.authorization.k8s.yaml.in | 388 ++++++++++++++++++ manifests/generated/virt-operator.yaml.in | 56 +++ manifests/release/kubevirt-operator.yaml.in | 81 +--- manifests/release/kubevirt.yaml.in | 3 +- .../release/olm/bundle/kubevirt-crds.yaml.in | 1 + .../olm/bundle/kubevirt-package.yaml.in | 4 + .../olm/bundle/kubevirt.vVERSION.csv.yaml.in | 111 +++++ .../olm/kubevirt-csv-preconditions.yaml.in | 9 + .../olm/kubevirt-operatorsource.yaml.in | 11 + .../release/olm/kubevirt-subscription.yaml.in | 10 + manifests/release/olm/operatorgroup.yaml.in | 5 + pkg/virt-operator/creation/components/crds.go | 4 +- .../creation/components/deployments.go | 128 +++++- pkg/virt-operator/creation/rbac/BUILD.bazel | 1 + pkg/virt-operator/creation/rbac/operator.go | 283 +++++++++++++ tools/manifest-templator/BUILD.bazel | 8 +- .../manifest-templator/manifest-templator.go | 103 ++++- .../resource-generator/resource-generator.go | 20 +- tools/util/marshaller.go | 7 +- tools/vms-generator/utils/utils.go | 4 - 36 files changed, 1542 insertions(+), 255 deletions(-) create mode 100644 assets/kubevirt_logo.png create mode 100644 docs/devel/olm-integration.md create mode 100644 hack/builder/version.sh create mode 100755 hack/olm.sh create mode 100644 manifests/generated/rbac-cluster.authorization.k8s.yaml.in rename manifests/generated/{rbac.authorization.k8s.yaml.in => rbac-kubevirt.authorization.k8s.yaml.in} (67%) create mode 100644 manifests/generated/rbac-operator.authorization.k8s.yaml.in create mode 100644 manifests/generated/virt-operator.yaml.in create mode 100644 manifests/release/olm/bundle/kubevirt-crds.yaml.in create mode 100644 manifests/release/olm/bundle/kubevirt-package.yaml.in create mode 100644 manifests/release/olm/bundle/kubevirt.vVERSION.csv.yaml.in create mode 100644 manifests/release/olm/kubevirt-csv-preconditions.yaml.in create mode 100644 manifests/release/olm/kubevirt-operatorsource.yaml.in create mode 100644 manifests/release/olm/kubevirt-subscription.yaml.in create mode 100644 manifests/release/olm/operatorgroup.yaml.in create mode 100644 pkg/virt-operator/creation/rbac/operator.go diff --git a/.travis.yml b/.travis.yml index 49e05127497f..64e145e35368 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ script: - make apidocs - make client-python - make manifests DOCKER_PREFIX="docker.io/kubevirt" DOCKER_TAG=$TRAVIS_TAG # falls back to latest if not on a tag +- make olm-verify deploy: - provider: script diff --git a/Makefile b/Makefile index 6aee53189b88..28845547732b 100644 --- a/Makefile +++ b/Makefile @@ -90,7 +90,7 @@ verify-build: hack/verify-build.sh manifests: - hack/dockerized "DOCKER_PREFIX=${DOCKER_PREFIX} DOCKER_TAG=${DOCKER_TAG} IMAGE_PULL_POLICY=${IMAGE_PULL_POLICY} VERBOSITY=${VERBOSITY} ./hack/build-manifests.sh" + hack/dockerized "CSV_VERSION=${CSV_VERSION} DOCKER_PREFIX=${DOCKER_PREFIX} DOCKER_TAG=${DOCKER_TAG} IMAGE_PULL_POLICY=${IMAGE_PULL_POLICY} VERBOSITY=${VERBOSITY} ./hack/build-manifests.sh" .release-functest: make functest > .release-functest 2>&1 @@ -121,6 +121,12 @@ builder-build: builder-publish: ./hack/builder/publish.sh +olm-verify: + hack/dockerized "./hack/olm.sh verify" + +olm-push: + hack/dockerized "CSV_VERSION=${CSV_VERSION} QUAY_USERNAME=${QUAY_USERNAME} QUAY_PASSWORD=${QUAY_PASSWORD} ./hack/olm.sh push" + .PHONY: \ go-build \ go-test \ @@ -145,4 +151,6 @@ builder-publish: cluster-down \ cluster-clean \ cluster-deploy \ - cluster-sync + cluster-sync \ + olm-verify \ + olm-push diff --git a/assets/kubevirt_logo.png b/assets/kubevirt_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..9e15e7ffdd18a6a675332aeb72f17bb557a5e041 GIT binary patch literal 11917 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 v1.11 for this. You might want to use a OKD cluster with OLM and Marketplace already installed. +Note 2: You need a Quay.io account + +- create manifests with your repository and version info, e.g.: + + TODO: actually use CSV_VERSION!!! + + `CSV_VERSION= DOCKER_PREFIX="docker.io/" DOCKER_TAG="" sh -c 'make generate && make manifests'` +- verify manifests: + `make olm-verify` +- push images: + `DOCKER_PREFIX="index.docker.io/" DOCKER_TAG="" make bazel-push-images` +- push the operator bundle: + `CSV_VERSION= QUAY_USER= QUAY_PASSWORD= make olm-push` + Note: you need to update the CSV version (and so run `make manifests`) on every push! (or maybe delete an old version before pushing again?) + +- install OLM and Marketplace (see below) + +- install KubeVirt OperatorSource: + `cd _out/manifests/release/olm` + `kubectl apply -f kubevirt-operatorsource.yaml` +- check that a CatalogSourceConfig and a CatalogSource were created in the marketplace namespace +- WORKAROUND: the OKD console only shows operators from CatalogSources in the `olm` namespace. In order to get it there, + you need to edit the CatalogSourceConfig and change the targetNamespace from `marketplace` to `olm`. The new + CatalogSource should be created automatically. +- create the kubevirt namespace: + `kubectl create ns kubevirt` +- install the OperatorGroup for the new namespace: + `kubectl apply -f operatorgroup.yaml` +- create a Subscription: + `kubectl apply -f kubevirt-subsription.yaml` +- check that a InstallPlan was created +- check that the KubeVirt operator was installed +- install a KubeVirt CR + +Bonus: install the OKD Console: + +- we need cluster-admin permissions for the kube-system:default account: + `kubectl create clusterrolebinding defaultadmin --clusterrole cluster-admin --serviceaccount kube-system:default` +- in the OLM repository, run `./scripts/run_console_local.sh` +- open `localhost:9000` in a browser + +## Release a new version + +Travis cares for this on every release. + +## Installing OLM on Kubernetes + +- clone github.com/operator-framework/operator-lifecycle-manager +- `cd deploy/upstream/quickstart` +- `kubectl apply -f olm.yaml` +- if you get an error, try again, CRDs might have been too slow + +## Installing Marketplace on Kubernetes + +- clone github.com/operator-framework/operator-marketplace +- `cd deploy/upstream/manifests` +- `kubectl apply -f upstream/` +- if you get an error about rolebinding, repeat with `--validate=false` + +## Sources + +CSV description: https://github.com/operator-framework/operator-lifecycle-manager/blob/master/Documentation/design/building-your-csv.md +Publish bundles: https://github.com/operator-framework/community-operators/blob/master/docs/testing-operators.md +Install OLM: https://github.com/operator-framework/operator-lifecycle-manager/blob/master/Documentation/install/install.md +Install and use Marketplace: https://github.com/operator-framework/operator-marketplace + +## Important + +- the Quay repo name needs to match the package name (https://github.com/operator-framework/operator-marketplace/issues/122#issuecomment-470820491) \ No newline at end of file diff --git a/hack/build-manifests.sh b/hack/build-manifests.sh index 3d2650a3f4b7..6a361b49352f 100755 --- a/hack/build-manifests.sh +++ b/hack/build-manifests.sh @@ -23,6 +23,7 @@ source hack/common.sh source hack/config.sh manifest_docker_prefix=${manifest_docker_prefix-${docker_prefix}} +kubevirt_logo_path="assets/kubevirt_logo.png" rm -rf ${MANIFESTS_OUT_DIR} rm -rf ${MANIFEST_TEMPLATES_OUT_DIR} @@ -44,12 +45,18 @@ done # then process variables args=$(cd ${KUBEVIRT_DIR}/manifests && find . -type f -name "*.yaml.in.tmp") for arg in $args; do + + infile=${KUBEVIRT_DIR}/manifests/${arg} + final_out_dir=$(dirname ${MANIFESTS_OUT_DIR}/${arg}) - final_templates_out_dir=$(dirname ${MANIFEST_TEMPLATES_OUT_DIR}/${arg}) mkdir -p ${final_out_dir} + + final_templates_out_dir=$(dirname ${MANIFEST_TEMPLATES_OUT_DIR}/${arg}) mkdir -p ${final_templates_out_dir} + manifest=$(basename -s .in.tmp ${arg}) - infile=${KUBEVIRT_DIR}/manifests/${arg} + manifest="${manifest/VERSION/${csv_version}}" + outfile=${final_out_dir}/${manifest} template_outfile=${final_templates_out_dir}/${manifest}.j2 @@ -61,6 +68,8 @@ for arg in $args; do --container-tag=${docker_tag} \ --image-pull-policy=${image_pull_policy} \ --verbosity=${verbosity} \ + --csv-version=${csv_version} \ + --kubevirt-logo-path=${kubevirt_logo_path} \ --input-file=${infile} >${outfile} ${KUBEVIRT_DIR}/tools/manifest-templator/manifest-templator \ @@ -71,6 +80,8 @@ for arg in $args; do --container-tag="{{ docker_tag }}" \ --image-pull-policy="{{ image_pull_policy }}" \ --verbosity=${verbosity} \ + --csv-version=${csv_version} \ + --kubevirt-logo-path=${kubevirt_logo_path} \ --input-file=${infile} >${template_outfile} done diff --git a/hack/builder/Dockerfile b/hack/builder/Dockerfile index 3f7bc2e87ac5..4d53741e4fd3 100644 --- a/hack/builder/Dockerfile +++ b/hack/builder/Dockerfile @@ -1,6 +1,6 @@ FROM fedora:28 -ENV LIBVIRT_VERSION 5.0.0 +ENV LIBVIRT_VERSION 5.1.0 # Install packages RUN dnf install -y dnf-plugins-core && \ @@ -23,7 +23,9 @@ RUN dnf install -y dnf-plugins-core && \ rsync-daemon \ rsync \ qemu-img \ - protobuf-compiler && \ + protobuf-compiler \ + python3-devel \ + redhat-rpm-config && \ dnf -y clean all ENV GIMME_GO_VERSION=1.11.5 diff --git a/hack/builder/build.sh b/hack/builder/build.sh index ac541f356df9..02ff5fde01e6 100755 --- a/hack/builder/build.sh +++ b/hack/builder/build.sh @@ -5,4 +5,6 @@ SCRIPT_DIR="$( pwd )" -docker build -t kubevirt/builder:28-5.0.0 -f ${SCRIPT_DIR}/Dockerfile ${SCRIPT_DIR} +. ${SCRIPT_DIR}/version.sh + +docker build -t kubevirt/builder:${VERSION} -f ${SCRIPT_DIR}/Dockerfile ${SCRIPT_DIR} diff --git a/hack/builder/publish.sh b/hack/builder/publish.sh index d91e1f20b153..4a1b39628753 100755 --- a/hack/builder/publish.sh +++ b/hack/builder/publish.sh @@ -1,4 +1,11 @@ #!/usr/bin/env bash -docker tag kubevirt/builder:28-5.0.0 docker.io/kubevirt/builder:28-5.0.0 -docker push docker.io/kubevirt/builder:28-5.0.0 +SCRIPT_DIR="$( + cd "$(dirname "$BASH_SOURCE[0]")" + pwd +)" + +. ${SCRIPT_DIR}/version.sh + +docker tag kubevirt/builder:${VERSION} docker.io/kubevirt/builder:${VERSION} +docker push docker.io/kubevirt/builder:${VERSION} diff --git a/hack/builder/version.sh b/hack/builder/version.sh new file mode 100644 index 000000000000..52f0305cec18 --- /dev/null +++ b/hack/builder/version.sh @@ -0,0 +1 @@ +VERSION=28-5.1.0 diff --git a/hack/config-default.sh b/hack/config-default.sh index 0762eaa090aa..a27b29c1c01f 100644 --- a/hack/config-default.sh +++ b/hack/config-default.sh @@ -9,3 +9,9 @@ namespace=kubevirt cdi_namespace=cdi image_pull_policy=${IMAGE_PULL_POLICY:-IfNotPresent} verbosity=${VERBOSITY:-2} + +# try to derive csv_version from docker tag. But it must start with x.y.z, without leading v +default_csv_version="${docker_tag/latest/0.0.0}" +default_csv_version="${default_csv_version/devel/0.0.0}" +[[ $default_csv_version == v* ]] && default_csv_version="${default_csv_version/v/}" +csv_version=${CSV_VERSION:-$default_csv_version} diff --git a/hack/config.sh b/hack/config.sh index 3549811f5c79..f6d70ccd6f7e 100644 --- a/hack/config.sh +++ b/hack/config.sh @@ -1,5 +1,5 @@ unset binaries docker_images docker_prefix docker_tag docker_tag_alt manifest_templates \ - master_ip network_provider kubeconfig manifest_docker_prefix namespace image_pull_policy verbosity + master_ip network_provider kubeconfig manifest_docker_prefix namespace image_pull_policy verbosity csv_version KUBEVIRT_PROVIDER=${KUBEVIRT_PROVIDER:-${PROVIDER}} @@ -13,4 +13,4 @@ test -f "hack/config-provider-${KUBEVIRT_PROVIDER}.sh" && source hack/config-pro test -f "hack/config-local.sh" && source hack/config-local.sh export binaries docker_images docker_prefix docker_tag docker_tag_alt manifest_templates \ - master_ip network_provider kubeconfig namespace image_pull_policy verbosity + master_ip network_provider kubeconfig namespace image_pull_policy verbosity csv_version diff --git a/hack/generate.sh b/hack/generate.sh index fc1472cd06e0..6945b5d54426 100755 --- a/hack/generate.sh +++ b/hack/generate.sh @@ -23,11 +23,14 @@ ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=vm >${KUBEVIR ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=vmim >${KUBEVIRT_DIR}/manifests/generated/vmim-resource.yaml ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=kv >${KUBEVIRT_DIR}/manifests/generated/kv-resource.yaml ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=kv-cr --namespace={{.Namespace}} --pullPolicy={{.ImagePullPolicy}} >${KUBEVIRT_DIR}/manifests/generated/kubevirt-cr.yaml.in -${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=rbac --namespace={{.Namespace}} >${KUBEVIRT_DIR}/manifests/generated/rbac.authorization.k8s.yaml.in +${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=kubevirt-rbac --namespace={{.Namespace}} >${KUBEVIRT_DIR}/manifests/generated/rbac-kubevirt.authorization.k8s.yaml.in +${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=cluster-rbac --namespace={{.Namespace}} >${KUBEVIRT_DIR}/manifests/generated/rbac-cluster.authorization.k8s.yaml.in +${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=operator-rbac --namespace={{.Namespace}} >${KUBEVIRT_DIR}/manifests/generated/rbac-operator.authorization.k8s.yaml.in ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=prometheus --namespace={{.Namespace}} >${KUBEVIRT_DIR}/manifests/generated/prometheus.yaml.in ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=virt-api --namespace={{.Namespace}} --repository={{.DockerPrefix}} --version={{.DockerTag}} --pullPolicy={{.ImagePullPolicy}} --verbosity={{.Verbosity}} >${KUBEVIRT_DIR}/manifests/generated/virt-api.yaml.in ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=virt-controller --namespace={{.Namespace}} --repository={{.DockerPrefix}} --version={{.DockerTag}} --pullPolicy={{.ImagePullPolicy}} --verbosity={{.Verbosity}} >${KUBEVIRT_DIR}/manifests/generated/virt-controller.yaml.in ${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=virt-handler --namespace={{.Namespace}} --repository={{.DockerPrefix}} --version={{.DockerTag}} --pullPolicy={{.ImagePullPolicy}} --verbosity={{.Verbosity}} >${KUBEVIRT_DIR}/manifests/generated/virt-handler.yaml.in +${KUBEVIRT_DIR}/tools/resource-generator/resource-generator --type=virt-operator --namespace={{.Namespace}} --repository={{.DockerPrefix}} --version={{.DockerTag}} --pullPolicy={{.ImagePullPolicy}} --verbosity={{.Verbosity}} >${KUBEVIRT_DIR}/manifests/generated/virt-operator.yaml.in (cd ${KUBEVIRT_DIR}/tools/vms-generator/ && go build) vms_docker_prefix=${DOCKER_PREFIX:-registry:5000/kubevirt} diff --git a/hack/kubevirt-builder/Dockerfile b/hack/kubevirt-builder/Dockerfile index 1d5b29f36a77..612bef686c24 100644 --- a/hack/kubevirt-builder/Dockerfile +++ b/hack/kubevirt-builder/Dockerfile @@ -1,4 +1,4 @@ -FROM kubevirt/builder@sha256:cd662847df816a0c5cf1a99dcb905301d305befe93d50bee8d00fdd5c74beb19 +FROM kubevirt/builder:28-5.1.0 ENV GIMME_GO_VERSION=1.11.5 ENV GOPATH="/go" GOBIN="/usr/bin" @@ -13,7 +13,7 @@ RUN \ go get -u github.com/rmohr/go-swagger-utils/swagger-doc && \ go get -u github.com/onsi/ginkgo/ginkgo -RUN pip install j2cli +RUN pip install j2cli && pip3 install operator-courier COPY rsyncd.conf /etc/rsyncd.conf diff --git a/hack/olm.sh b/hack/olm.sh new file mode 100755 index 000000000000..1f83cd042272 --- /dev/null +++ b/hack/olm.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# +# This file is part of the KubeVirt project +# +# 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. +# +# Copyright 2019 Red Hat, Inc. +# + +set -e + +source $(dirname "$0")/common.sh + +if [ $# -ne 1 ]; then + echo "usage: ${0} verify | push" +fi + +BUNDLE_DIR=${OUT_DIR}/manifests/release/olm/bundle +echo "using these manifests:" +ls ${BUNDLE_DIR} + +case ${1} in + +verify) + + IFS= + result=$(operator-courier verify ${BUNDLE_DIR} 2>&1) + echo $result + + if [[ $result =~ "ERROR" ]]; then + echo "olm verify failed!" + exit 1 + fi + + echo "olm verify success!" + exit 0 + + ;; + +push) + + if [[ -z "$CSV_VERSION" ]] || [[ -z "$QUAY_USERNAME" ]] || [[ -z "$QUAY_USERNAME" ]]; then + echo "please set CSV_VERSION, QUAY_USERNAME and QUAY_PASSWORD" + exit 1 + fi + + echo "getting auth token from Quay" + AUTH_TOKEN=$(curl -sH "Content-Type: application/json" -XPOST https://quay.io/cnr/api/v1/users/login -d ' + { + "user": { + "username": "'"${QUAY_USERNAME}"'", + "password": "'"${QUAY_PASSWORD}"'" + } + }' | jq -r '.token') + + echo "pushing bundle" + operator-courier push "$BUNDLE_DIR" "$QUAY_USERNAME" kubevirt "$CSV_VERSION" "$AUTH_TOKEN" + + ;; +esac diff --git a/manifests/generated/rbac-cluster.authorization.k8s.yaml.in b/manifests/generated/rbac-cluster.authorization.k8s.yaml.in new file mode 100644 index 000000000000..03fb93f51bff --- /dev/null +++ b/manifests/generated/rbac-cluster.authorization.k8s.yaml.in @@ -0,0 +1,135 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + labels: + kubernetes.io/bootstrapping: rbac-defaults + kubevirt.io: "" + name: kubevirt.io:default +rules: +- apiGroups: + - subresources.kubevirt.io + resources: + - version + verbs: + - get + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + annotations: + rbac.authorization.kubernetes.io/autoupdate: "true" + labels: + kubevirt.io: "" + name: kubevirt.io:default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubevirt.io:default +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated +- apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:unauthenticated +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + kubevirt.io: "" + rbac.authorization.k8s.io/aggregate-to-admin: "true" + name: kubevirt.io:admin +rules: +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/restart + verbs: + - put + - update +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + kubevirt.io: "" + rbac.authorization.k8s.io/aggregate-to-edit: "true" + name: kubevirt.io:edit +rules: +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/restart + verbs: + - put + - update +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + kubevirt.io: "" + rbac.authorization.k8s.io/aggregate-to-view: "true" + name: kubevirt.io:view +rules: +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + verbs: + - get + - list + - watch diff --git a/manifests/generated/rbac.authorization.k8s.yaml.in b/manifests/generated/rbac-kubevirt.authorization.k8s.yaml.in similarity index 67% rename from manifests/generated/rbac.authorization.k8s.yaml.in rename to manifests/generated/rbac-kubevirt.authorization.k8s.yaml.in index 40559d501d96..70b359853293 100644 --- a/manifests/generated/rbac.authorization.k8s.yaml.in +++ b/manifests/generated/rbac-kubevirt.authorization.k8s.yaml.in @@ -1,139 +1,4 @@ --- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - annotations: - rbac.authorization.kubernetes.io/autoupdate: "true" - labels: - kubernetes.io/bootstrapping: rbac-defaults - kubevirt.io: "" - name: kubevirt.io:default -rules: -- apiGroups: - - subresources.kubevirt.io - resources: - - version - verbs: - - get - - list ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - annotations: - rbac.authorization.kubernetes.io/autoupdate: "true" - labels: - kubevirt.io: "" - name: kubevirt.io:default -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: kubevirt.io:default -subjects: -- apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated -- apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:unauthenticated ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - kubevirt.io: "" - rbac.authorization.k8s.io/aggregate-to-admin: "true" - name: kubevirt.io:admin -rules: -- apiGroups: - - subresources.kubevirt.io - resources: - - virtualmachineinstances/console - - virtualmachineinstances/vnc - verbs: - - get -- apiGroups: - - subresources.kubevirt.io - resources: - - virtualmachines/restart - verbs: - - put - - update -- apiGroups: - - kubevirt.io - resources: - - virtualmachines - - virtualmachineinstances - - virtualmachineinstancepresets - - virtualmachineinstancereplicasets - verbs: - - get - - delete - - create - - update - - patch - - list - - watch - - deletecollection ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - kubevirt.io: "" - rbac.authorization.k8s.io/aggregate-to-edit: "true" - name: kubevirt.io:edit -rules: -- apiGroups: - - subresources.kubevirt.io - resources: - - virtualmachineinstances/console - - virtualmachineinstances/vnc - verbs: - - get -- apiGroups: - - subresources.kubevirt.io - resources: - - virtualmachines/restart - verbs: - - put - - update -- apiGroups: - - kubevirt.io - resources: - - virtualmachines - - virtualmachineinstances - - virtualmachineinstancepresets - - virtualmachineinstancereplicasets - verbs: - - get - - delete - - create - - update - - patch - - list - - watch ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - labels: - kubevirt.io: "" - rbac.authorization.k8s.io/aggregate-to-view: "true" - name: kubevirt.io:view -rules: -- apiGroups: - - kubevirt.io - resources: - - virtualmachines - - virtualmachineinstances - - virtualmachineinstancepresets - - virtualmachineinstancereplicasets - verbs: - - get - - list - - watch ---- apiVersion: v1 kind: ServiceAccount metadata: diff --git a/manifests/generated/rbac-operator.authorization.k8s.yaml.in b/manifests/generated/rbac-operator.authorization.k8s.yaml.in new file mode 100644 index 000000000000..d53fc9659f5a --- /dev/null +++ b/manifests/generated/rbac-operator.authorization.k8s.yaml.in @@ -0,0 +1,388 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator + namespace: {{.Namespace}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator +rules: +- apiGroups: + - kubevirt.io + resources: + - kubevirts + verbs: + - get + - list + - watch + - patch + - update +- apiGroups: + - "" + resources: + - serviceaccounts + - services + verbs: + - get + - list + - watch + - create + - update + - delete +- apiGroups: + - batch + resources: + - jobs + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - apps + resources: + - deployments + - daemonsets + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + - roles + - rolebindings + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - create + - delete +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - get + - list + - watch +- apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - get + - patch + - update +- apiGroups: + - admissionregistration.k8s.io + resources: + - validatingwebhookconfigurations + - mutatingwebhookconfigurations + verbs: + - get + - create + - update +- apiGroups: + - apiregistration.k8s.io + resources: + - apiservices + verbs: + - get + - create + - update +- apiGroups: + - "" + resources: + - pods + verbs: + - get + - list +- apiGroups: + - "" + resources: + - pods/exec + verbs: + - create +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancemigrations + verbs: + - get + - list + - watch + - delete +- apiGroups: + - kubevirt.io + resources: + - virtualmachineinstancepresets + verbs: + - watch + - list +- apiGroups: + - "" + resourceNames: + - extension-apiserver-authentication + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - limitranges + verbs: + - watch + - list +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - delete + - update + - create +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - pods + - configmaps + - endpoints + verbs: + - get + - list + - watch + - delete + - update + - create +- apiGroups: + - "" + resources: + - events + verbs: + - update + - create + - patch +- apiGroups: + - "" + resources: + - pods/finalizers + verbs: + - update +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - update + - patch +- apiGroups: + - "" + resources: + - persistentvolumeclaims + verbs: + - get + - list + - watch +- apiGroups: + - kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - cdi.kubevirt.io + resources: + - '*' + verbs: + - '*' +- apiGroups: + - k8s.cni.cncf.io + resources: + - network-attachment-definitions + verbs: + - get + - list + - watch +- apiGroups: + - kubevirt.io + resources: + - virtualmachineinstances + verbs: + - update + - list + - watch +- apiGroups: + - "" + resources: + - secrets + - persistentvolumeclaims + verbs: + - get +- apiGroups: + - "" + resources: + - nodes + verbs: + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - subresources.kubevirt.io + resources: + - version + verbs: + - get + - list +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/restart + verbs: + - put + - update +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + verbs: + - get + - delete + - create + - update + - patch + - list + - watch + - deletecollection +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachineinstances/console + - virtualmachineinstances/vnc + verbs: + - get +- apiGroups: + - subresources.kubevirt.io + resources: + - virtualmachines/restart + verbs: + - put + - update +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + verbs: + - get + - delete + - create + - update + - patch + - list + - watch +- apiGroups: + - kubevirt.io + resources: + - virtualmachines + - virtualmachineinstances + - virtualmachineinstancepresets + - virtualmachineinstancereplicasets + verbs: + - get + - list + - watch +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + kubevirt.io: "" + name: kubevirt-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kubevirt-operator +subjects: +- kind: ServiceAccount + name: kubevirt-operator + namespace: {{.Namespace}} diff --git a/manifests/generated/virt-operator.yaml.in b/manifests/generated/virt-operator.yaml.in new file mode 100644 index 000000000000..fa18554b5c12 --- /dev/null +++ b/manifests/generated/virt-operator.yaml.in @@ -0,0 +1,56 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + kubevirt.io: virt-operator + name: virt-operator + namespace: {{.Namespace}} +spec: + replicas: 1 + selector: + matchLabels: + kubevirt.io: virt-operator + strategy: {} + template: + metadata: + annotations: + scheduler.alpha.kubernetes.io/critical-pod: "" + scheduler.alpha.kubernetes.io/tolerations: '[{"key":"CriticalAddonsOnly","operator":"Exists"}]' + labels: + kubevirt.io: virt-operator + prometheus.kubevirt.io: "" + name: virt-operator + spec: + containers: + - command: + - virt-operator + - --port + - "8443" + - -v + - {{.Verbosity}} + env: + - name: OPERATOR_IMAGE + value: {{.DockerPrefix}}/virt-operator:{{.DockerTag}} + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + image: {{.DockerPrefix}}/virt-operator:{{.DockerTag}} + imagePullPolicy: {{.ImagePullPolicy}} + name: virt-operator + ports: + - containerPort: 8443 + name: metrics + protocol: TCP + readinessProbe: + httpGet: + path: /metrics + port: 8443 + scheme: HTTPS + initialDelaySeconds: 5 + timeoutSeconds: 10 + resources: {} + securityContext: + runAsNonRoot: true + serviceAccountName: kubevirt-operator diff --git a/manifests/release/kubevirt-operator.yaml.in b/manifests/release/kubevirt-operator.yaml.in index a5df3c9ccf65..9b2a177b03f7 100644 --- a/manifests/release/kubevirt-operator.yaml.in +++ b/manifests/release/kubevirt-operator.yaml.in @@ -28,82 +28,5 @@ rules: - list - watch - deletecollection ---- -kind: ServiceAccount -apiVersion: v1 -metadata: - name: kubevirt-operator - namespace: {{.Namespace}} - labels: - operator.kubevirt.io: "" ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: kubevirt-operator - namespace: {{.Namespace}} - labels: - operator.kubevirt.io: "" -roleRef: - kind: ClusterRole - name: cluster-admin - apiGroup: rbac.authorization.k8s.io -subjects: - - kind: ServiceAccount - name: kubevirt-operator - namespace: {{.Namespace}} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: virt-operator - namespace: {{.Namespace}} - labels: - operator.kubevirt.io: "virt-operator" -spec: - replicas: 1 - selector: - matchLabels: - operator.kubevirt.io: virt-operator - template: - metadata: - annotations: - scheduler.alpha.kubernetes.io/critical-pod: "" - scheduler.alpha.kubernetes.io/tolerations: | - [ - { - "key": "CriticalAddonsOnly", - "operator": "Exists" - } - ] - labels: - operator.kubevirt.io: virt-operator - prometheus.kubevirt.io: "" - spec: - serviceAccountName: kubevirt-operator - containers: - - name: virt-operator - image: &image {{.DockerPrefix}}/virt-operator:{{.DockerTag}} - imagePullPolicy: {{.ImagePullPolicy}} - command: - - virt-operator - - --port - - "8443" - - -v - - {{.Verbosity}} - ports: - - containerPort: 8443 - name: "metrics" - protocol: "TCP" - readinessProbe: - httpGet: - scheme: HTTPS - port: "metrics" - path: "/metrics" - initialDelaySeconds: 5 - periodSeconds: 10 - env: - - name: OPERATOR_IMAGE - value: *image - securityContext: - runAsNonRoot: true +{{index .GeneratedManifests "rbac-operator.authorization.k8s.yaml.in"}} +{{index .GeneratedManifests "virt-operator.yaml.in"}} diff --git a/manifests/release/kubevirt.yaml.in b/manifests/release/kubevirt.yaml.in index 7e2fd4f67157..c97227b1b78e 100644 --- a/manifests/release/kubevirt.yaml.in +++ b/manifests/release/kubevirt.yaml.in @@ -6,7 +6,8 @@ metadata: kubevirt.io: "" name: {{.Namespace}} {{index .GeneratedManifests "prometheus.yaml.in"}} -{{index .GeneratedManifests "rbac.authorization.k8s.yaml.in"}} +{{index .GeneratedManifests "rbac-cluster.authorization.k8s.yaml.in"}} +{{index .GeneratedManifests "rbac-kubevirt.authorization.k8s.yaml.in"}} {{index .GeneratedManifests "virt-api.yaml.in"}} {{index .GeneratedManifests "virt-controller.yaml.in"}} {{index .GeneratedManifests "virt-handler.yaml.in"}} diff --git a/manifests/release/olm/bundle/kubevirt-crds.yaml.in b/manifests/release/olm/bundle/kubevirt-crds.yaml.in new file mode 100644 index 000000000000..5e4ea66bd04a --- /dev/null +++ b/manifests/release/olm/bundle/kubevirt-crds.yaml.in @@ -0,0 +1 @@ +{{index .GeneratedManifests "kv-resource.yaml"}} diff --git a/manifests/release/olm/bundle/kubevirt-package.yaml.in b/manifests/release/olm/bundle/kubevirt-package.yaml.in new file mode 100644 index 000000000000..c83f7d95e158 --- /dev/null +++ b/manifests/release/olm/bundle/kubevirt-package.yaml.in @@ -0,0 +1,4 @@ +packageName: kubevirt +channels: + - name: alpha + currentCSV: kubevirtoperator.v{{.CsvVersion}} diff --git a/manifests/release/olm/bundle/kubevirt.vVERSION.csv.yaml.in b/manifests/release/olm/bundle/kubevirt.vVERSION.csv.yaml.in new file mode 100644 index 000000000000..073e449792d0 --- /dev/null +++ b/manifests/release/olm/bundle/kubevirt.vVERSION.csv.yaml.in @@ -0,0 +1,111 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + name: kubevirtoperator.v{{.CsvVersion}} + namespace: placeholder + annotations: + capabilities: "Full Lifecycle" + categories: "Virtualization" + alm-examples: | + [ + { + "apiVersion":"kubevirt.io/v1alpha3", + "kind":"KubeVirt", + "metadata": { + "name":"kubevirt", + "namespace":"kubevirt" + }, + "spec": { + "imagePullPolicy":"Always" + } + } + ] + description: Creates and maintains KubeVirt deployments +spec: + displayName: KubeVirt + description: | + KubeVirt is a cluster add-on that provides a way to run virtualized workloads alongside containerized workload in a Kubernetes / OpenShift native way. + + _The KubeVirt Operator does not support updates yet._ + keywords: + - KubeVirt + - Virtualization + version: {{.CsvVersion}} + maturity: alpha + #replaces: kubevirtoperator.v?.?.? + maintainers: + - name: Red Hat + email: kubevirt-dev@googlegroups.com + provider: + name: Red Hat + links: + - name: KubeVirt + url: https://kubevirt.io + - name: Source Code + url: https://github.com/kubevirt/kubevirt + icon: + - base64data: {{.KubeVirtLogo}} + mediatype: image/png + labels: + alm-owner-kubevirt: kubevirtoperator + operated-by: kubevirtoperator + selector: + matchLabels: + alm-owner-kubevirt: kubevirtoperator + operated-by: kubevirtoperator + installModes: + - type: OwnNamespace + supported: true + - type: SingleNamespace + supported: true + - type: MultiNamespace + supported: true + - type: AllNamespaces + supported: true + install: + strategy: deployment + spec: + clusterPermissions: + - serviceAccountName: kubevirt-operator + rules: +{{.OperatorRules}} + deployments: + - name: virt-operator + spec: +{{.OperatorDeploymentSpec}} + customresourcedefinitions: + owned: + - name: kubevirts.kubevirt.io + version: v1alpha3 + kind: KubeVirt + displayName: KubeVirt deployment + description: Represents a KubeVirt deployment. + specDescriptors: + - description: The ImagePullPolicy to use for the KubeVirt components. + displayName: ImagePullPolicy + path: imagePullPolicy + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes:imagePullPolicy' + statusDescriptors: + - description: The deployment phase. + displayName: Phase + path: phase + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes.phase' + - description: Explanation for the current status of the cluster. + displayName: Conditions + path: conditions + x-descriptors: + - 'urn:alm:descriptor:io.kubernetes.conditions' + - description: The observed version of the KubeVirt deployment. + displayName: Observed KubeVirt Version + path: observedKubeVirtVersion + - 'urn:alm:descriptor:text' + - description: The targeted version of the KubeVirt deployment. + displayName: Target KubeVirt Version + path: targetKubeVirtVersion + - 'urn:alm:descriptor:text' + - description: The version of the KubeVirt Operator. + displayName: KubeVirt Operator Version + path: operatorVersion + - 'urn:alm:descriptor:text' diff --git a/manifests/release/olm/kubevirt-csv-preconditions.yaml.in b/manifests/release/olm/kubevirt-csv-preconditions.yaml.in new file mode 100644 index 000000000000..b64a5ee21109 --- /dev/null +++ b/manifests/release/olm/kubevirt-csv-preconditions.yaml.in @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + labels: + kubevirt.io: "" + name: {{.Namespace}} +{{index .GeneratedManifests "kv-resource.yaml"}} +{{index .GeneratedManifests "rbac-operator.authorization.k8s.yaml.in"}} diff --git a/manifests/release/olm/kubevirt-operatorsource.yaml.in b/manifests/release/olm/kubevirt-operatorsource.yaml.in new file mode 100644 index 000000000000..6daaf7513571 --- /dev/null +++ b/manifests/release/olm/kubevirt-operatorsource.yaml.in @@ -0,0 +1,11 @@ +apiVersion: marketplace.redhat.com/v1alpha1 +kind: OperatorSource +metadata: + name: kubevirt + namespace: marketplace +spec: + type: appregistry + endpoint: https://quay.io/cnr + registryNamespace: kubevirt + displayName: "KubeVirt" + publisher: "Red Hat" diff --git a/manifests/release/olm/kubevirt-subscription.yaml.in b/manifests/release/olm/kubevirt-subscription.yaml.in new file mode 100644 index 000000000000..b67f61f68991 --- /dev/null +++ b/manifests/release/olm/kubevirt-subscription.yaml.in @@ -0,0 +1,10 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: Subscription +metadata: + name: kubevirt + namespace: {{.Namespace}} +spec: + channel: alpha + name: kubevirt + source: kubevirt + sourceNamespace: olm diff --git a/manifests/release/olm/operatorgroup.yaml.in b/manifests/release/olm/operatorgroup.yaml.in new file mode 100644 index 000000000000..489c28fa7b7d --- /dev/null +++ b/manifests/release/olm/operatorgroup.yaml.in @@ -0,0 +1,5 @@ +apiVersion: operators.coreos.com/v1alpha2 +kind: OperatorGroup +metadata: + name: {{.Namespace}} + namespace: {{.Namespace}} diff --git a/pkg/virt-operator/creation/components/crds.go b/pkg/virt-operator/creation/components/crds.go index 2d2dff93b772..bbe82ceaa924 100644 --- a/pkg/virt-operator/creation/components/crds.go +++ b/pkg/virt-operator/creation/components/crds.go @@ -247,7 +247,9 @@ func NewKubeVirtCrd() *extv1beta1.CustomResourceDefinition { return crd } -// used by manifest generation +// Used by manifest generation +// If you change something, you probably need to change the CSV manifest too, +// see /manifests/release/kubevirt.vVERSION.csv.yaml.in func NewKubeVirtCR(namespace string, pullPolicy corev1.PullPolicy) *virtv1.KubeVirt { return &virtv1.KubeVirt{ TypeMeta: metav1.TypeMeta{ diff --git a/pkg/virt-operator/creation/components/deployments.go b/pkg/virt-operator/creation/components/deployments.go index 426819a165c2..40a4c3b39b34 100644 --- a/pkg/virt-operator/creation/components/deployments.go +++ b/pkg/virt-operator/creation/components/deployments.go @@ -180,17 +180,11 @@ func NewApiServerService(namespace string) *corev1.Service { func newPodTemplateSpec(name string, repository string, version string, pullPolicy corev1.PullPolicy) (*corev1.PodTemplateSpec, error) { - tolerations := []corev1.Toleration{ - { - Key: "CriticalAddonsOnly", - Operator: corev1.TolerationOpExists, - }, - } - tolerationsStr, err := json.Marshal(tolerations) - + tolerations, err := criticalAddonsToleration() if err != nil { - return nil, fmt.Errorf("unable to create service: %v", err) + return nil, fmt.Errorf("unable to create toleration: %v", err) } + return &corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ @@ -199,7 +193,7 @@ func newPodTemplateSpec(name string, repository string, version string, pullPoli }, Annotations: map[string]string{ "scheduler.alpha.kubernetes.io/critical-pod": "", - "scheduler.alpha.kubernetes.io/tolerations": string(tolerationsStr), + "scheduler.alpha.kubernetes.io/tolerations": string(tolerations), }, Name: name, }, @@ -468,9 +462,123 @@ func NewHandlerDaemonSet(namespace string, repository string, version string, pu } +// Used for manifest generation only +func NewOperatorDeployment(namespace string, repository string, version string, pullPolicy corev1.PullPolicy, verbosity string) (*appsv1.Deployment, error) { + + name := "virt-operator" + image := fmt.Sprintf("%s/%s:%s", repository, name, version) + + tolerations, err := criticalAddonsToleration() + if err != nil { + return nil, fmt.Errorf("unable to create toleration: %v", err) + } + + deployment := &appsv1.Deployment{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "apps/v1", + Kind: "Deployment", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + Labels: map[string]string{ + virtv1.AppLabel: name, + }, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: int32Ptr(1), + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + virtv1.AppLabel: name, + }, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + virtv1.AppLabel: name, + "prometheus.kubevirt.io": "", + }, + Annotations: map[string]string{ + "scheduler.alpha.kubernetes.io/critical-pod": "", + "scheduler.alpha.kubernetes.io/tolerations": string(tolerations), + }, + Name: name, + }, + Spec: corev1.PodSpec{ + ServiceAccountName: "kubevirt-operator", + Containers: []corev1.Container{ + { + Name: name, + Image: image, + ImagePullPolicy: pullPolicy, + Command: []string{ + "virt-operator", + "--port", + "8443", + "-v", + verbosity, + }, + Ports: []corev1.ContainerPort{ + { + Name: "metrics", + Protocol: corev1.ProtocolTCP, + ContainerPort: 8443, + }, + }, + ReadinessProbe: &corev1.Probe{ + Handler: corev1.Handler{ + HTTPGet: &corev1.HTTPGetAction{ + Scheme: corev1.URISchemeHTTPS, + Port: intstr.IntOrString{ + Type: intstr.Int, + IntVal: 8443, + }, + Path: "/metrics", + }, + }, + InitialDelaySeconds: 5, + TimeoutSeconds: 10, + }, + Env: []corev1.EnvVar{ + { + Name: "OPERATOR_IMAGE", + Value: image, + }, + { + Name: "WATCH_NAMESPACE", // not used yet + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.annotations['olm.targetNamespaces']", // filled by OLM + }, + }, + }, + }, + }, + }, + SecurityContext: &corev1.PodSecurityContext{ + RunAsNonRoot: boolPtr(true), + }, + }, + }, + }, + } + + return deployment, nil +} + func int32Ptr(i int32) *int32 { return &i } func boolPtr(b bool) *bool { return &b } +func criticalAddonsToleration() ([]byte, error) { + tolerations := []corev1.Toleration{ + { + Key: "CriticalAddonsOnly", + Operator: corev1.TolerationOpExists, + }, + } + tolerationsStr, err := json.Marshal(tolerations) + return tolerationsStr, err +} diff --git a/pkg/virt-operator/creation/rbac/BUILD.bazel b/pkg/virt-operator/creation/rbac/BUILD.bazel index ede197345703..b6a17264cfa9 100644 --- a/pkg/virt-operator/creation/rbac/BUILD.bazel +++ b/pkg/virt-operator/creation/rbac/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "cluster.go", "controller.go", "handler.go", + "operator.go", ], importpath = "kubevirt.io/kubevirt/pkg/virt-operator/creation/rbac", visibility = ["//visibility:public"], diff --git a/pkg/virt-operator/creation/rbac/operator.go b/pkg/virt-operator/creation/rbac/operator.go new file mode 100644 index 000000000000..e532147db993 --- /dev/null +++ b/pkg/virt-operator/creation/rbac/operator.go @@ -0,0 +1,283 @@ +/* + * This file is part of the KubeVirt project + * + * 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. + * + * Copyright 2019 Red Hat, Inc. + * + */ +package rbac + +import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + virtv1 "kubevirt.io/kubevirt/pkg/api/v1" +) + +// Used for manifest generation only, not by the operator itself +func GetAllOperator(namespace string) []interface{} { + return []interface{}{ + newOperatorServiceAccount(namespace), + NewOperatorClusterRole(), + newOperatorClusterRoleBinding(namespace), + } +} + +func newOperatorServiceAccount(namespace string) *corev1.ServiceAccount { + return &corev1.ServiceAccount{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "ServiceAccount", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: "kubevirt-operator", + Labels: map[string]string{ + virtv1.AppLabel: "", + }, + }, + } +} + +// pulic, because it's used in manifest-templator +func NewOperatorClusterRole() *rbacv1.ClusterRole { + // These are permissions needed by the operator itself. + // For successfully deploying KubeVirt with the operator, you need to add everything + // that the KubeVirt components' rules use, see below + // (you can't create rules with permissions you don't have yourself) + operatorRole := &rbacv1.ClusterRole{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "rbac.authorization.k8s.io/v1", + Kind: "ClusterRole", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "kubevirt-operator", + Labels: map[string]string{ + virtv1.AppLabel: "", + }, + }, + Rules: []rbacv1.PolicyRule{ + { + APIGroups: []string{ + "kubevirt.io", + }, + Resources: []string{ + "kubevirts", + }, + Verbs: []string{ + "get", + "list", + "watch", + "patch", + "update", + }, + }, + { + APIGroups: []string{ + "", + }, + Resources: []string{ + "serviceaccounts", + "services", + }, + Verbs: []string{ + "get", + "list", + "watch", + "create", + "update", + "delete", + }, + }, + { + APIGroups: []string{ + "batch", + }, + Resources: []string{ + "jobs", + }, + Verbs: []string{ + "get", + "list", + "watch", + "create", + "delete", + }, + }, + { + APIGroups: []string{ + "apps", + }, + Resources: []string{ + "deployments", + "daemonsets", + }, + Verbs: []string{ + "get", + "list", + "watch", + "create", + "delete", + }, + }, + { + APIGroups: []string{ + "rbac.authorization.k8s.io", + }, + Resources: []string{ + "clusterroles", + "clusterrolebindings", + "roles", + "rolebindings", + }, + Verbs: []string{ + "get", + "list", + "watch", + "create", + "delete", + }, + }, + { + APIGroups: []string{ + "apiextensions.k8s.io", + }, + Resources: []string{ + "customresourcedefinitions", + }, + Verbs: []string{ + "get", + "list", + "watch", + "create", + "delete", + }, + }, + { + APIGroups: []string{ + "security.openshift.io", + }, + Resources: []string{ + "securitycontextconstraints", + }, + Verbs: []string{ + "get", + "list", + "watch", + }, + }, + { + APIGroups: []string{ + "security.openshift.io", + }, + Resources: []string{ + "securitycontextconstraints", + }, + ResourceNames: []string{ + "privileged", + }, + Verbs: []string{ + "get", + "patch", + "update", + }, + }, + }, + } + + // now append all rules needed by KubeVirt's components + operatorRole.Rules = append(operatorRole.Rules, getKubeVirtComponentsRules()...) + return operatorRole +} + +func getKubeVirtComponentsRules() []rbacv1.PolicyRule { + + var rules []rbacv1.PolicyRule + + // namespace doesn't matter, we are only interested in the rules of both Roles and ClusterRoles + all := GetAllApiServer("") + all = append(all, GetAllController("")...) + all = append(all, GetAllHandler("")...) + all = append(all, GetAllCluster("")...) + + for _, resource := range all { + switch resource.(type) { + case *rbacv1.ClusterRole: + role, _ := resource.(*rbacv1.ClusterRole) + rules = append(rules, role.Rules...) + case *rbacv1.Role: + role, _ := resource.(*rbacv1.Role) + rules = append(rules, role.Rules...) + } + } + + // OLM doesn't support role refs + // so we need special handling for auth delegation for the apiserver, + // by adding the rules of the system:auth-delegator role manually + authDelegationRules := []rbacv1.PolicyRule{ + { + APIGroups: []string{ + "authentication.k8s.io", + }, + Resources: []string{ + "tokenreviews", + }, + Verbs: []string{ + "create", + }, + }, + { + APIGroups: []string{ + "authorization.k8s.io", + }, + Resources: []string{ + "subjectaccessreviews", + }, + Verbs: []string{ + "create", + }, + }, + } + rules = append(rules, authDelegationRules...) + + return rules +} + +func newOperatorClusterRoleBinding(namespace string) *rbacv1.ClusterRoleBinding { + return &rbacv1.ClusterRoleBinding{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "rbac.authorization.k8s.io/v1", + Kind: "ClusterRoleBinding", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "kubevirt-operator", + Labels: map[string]string{ + virtv1.AppLabel: "", + }, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: "kubevirt-operator", + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Namespace: namespace, + Name: "kubevirt-operator", + }, + }, + } +} diff --git a/tools/manifest-templator/BUILD.bazel b/tools/manifest-templator/BUILD.bazel index ac2fad63ecd0..c780458cccd4 100644 --- a/tools/manifest-templator/BUILD.bazel +++ b/tools/manifest-templator/BUILD.bazel @@ -5,7 +5,13 @@ go_library( srcs = ["manifest-templator.go"], importpath = "kubevirt.io/kubevirt/tools/manifest-templator", visibility = ["//visibility:private"], - deps = ["//vendor/github.com/spf13/pflag:go_default_library"], + deps = [ + "//pkg/virt-operator/creation/components:go_default_library", + "//pkg/virt-operator/creation/rbac:go_default_library", + "//tools/util:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", + ], ) go_binary( diff --git a/tools/manifest-templator/manifest-templator.go b/tools/manifest-templator/manifest-templator.go index c1e0420c2a00..0b109c50be96 100644 --- a/tools/manifest-templator/manifest-templator.go +++ b/tools/manifest-templator/manifest-templator.go @@ -20,24 +20,37 @@ package main import ( + "bufio" + "encoding/base64" "flag" "fmt" "io/ioutil" "os" "path/filepath" + "strings" "text/template" + "k8s.io/api/core/v1" + + "kubevirt.io/kubevirt/pkg/virt-operator/creation/components" + "kubevirt.io/kubevirt/pkg/virt-operator/creation/rbac" + "kubevirt.io/kubevirt/tools/util" + "github.com/spf13/pflag" ) type templateData struct { - Namespace string - CDINamespace string - DockerTag string - DockerPrefix string - ImagePullPolicy string - Verbosity string - GeneratedManifests map[string]string + Namespace string + CDINamespace string + DockerTag string + DockerPrefix string + ImagePullPolicy string + Verbosity string + CsvVersion string + OperatorDeploymentSpec string + OperatorRules string + KubeVirtLogo string + GeneratedManifests map[string]string } func main() { @@ -45,12 +58,15 @@ func main() { cdiNamespace := flag.String("cdi-namespace", "", "") dockerPrefix := flag.String("container-prefix", "", "") dockerTag := flag.String("container-tag", "", "") + csvVersion := flag.String("csv-version", "", "") imagePullPolicy := flag.String("image-pull-policy", "IfNotPresent", "") verbosity := flag.String("verbosity", "2", "") genDir := flag.String("generated-manifests-dir", "", "") inputFile := flag.String("input-file", "", "") processFiles := flag.Bool("process-files", false, "") processVars := flag.Bool("process-vars", false, "") + kubeVirtLogoPath := flag.String("kubevirt-logo-path", "", "") + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.CommandLine.ParseErrorsWhitelist.UnknownFlags = true pflag.Parse() @@ -70,6 +86,10 @@ func main() { data.DockerPrefix = *dockerPrefix data.ImagePullPolicy = *imagePullPolicy data.Verbosity = fmt.Sprintf("\"%s\"", *verbosity) + data.CsvVersion = *csvVersion + data.OperatorDeploymentSpec = getOperatorDeploymentSpec(data) + data.OperatorRules = getOperatorRules() + data.KubeVirtLogo = getKubeVirtLogo(*kubeVirtLogoPath) } else { // keep templates data.Namespace = "{{.Namespace}}" @@ -78,6 +98,10 @@ func main() { data.DockerPrefix = "{{.DockerPrefix}}" data.ImagePullPolicy = "{{.ImagePullPolicy}}" data.Verbosity = "{{.Verbosity}}" + data.CsvVersion = "{{.CsvVersion}}" + data.OperatorDeploymentSpec = "{{.OperatorDeploymentSpec}}" + data.OperatorRules = "{{.OperatorRules}}" + data.KubeVirtLogo = "{{.KubeVirtLogo}}" } if *processFiles { @@ -104,3 +128,68 @@ func main() { panic(err) } } + +func getOperatorRules() string { + rules := rbac.NewOperatorClusterRole().Rules + writer := strings.Builder{} + for _, rule := range rules { + err := util.MarshallObject(rule, &writer) + if err != nil { + panic(err) + } + } + return fixResourceString(writer.String(), 14) +} + +func getOperatorDeploymentSpec(data templateData) string { + deployment, err := components.NewOperatorDeployment(data.Namespace, data.DockerPrefix, data.DockerTag, v1.PullPolicy(data.ImagePullPolicy), data.Verbosity) + if err != nil { + panic(err) + } + writer := strings.Builder{} + err = util.MarshallObject(deployment.Spec, &writer) + if err != nil { + panic(err) + } + return fixResourceString(writer.String(), 12) +} + +func fixResourceString(in string, indention int) string { + out := strings.Builder{} + scanner := bufio.NewScanner(strings.NewReader(in)) + for scanner.Scan() { + line := scanner.Text() + // remove separator lines + if !strings.HasPrefix(line, "---") { + // indent so that it fits into the manifest + // spaces is is indention - 2, because we want to have 2 spaces less for being able to start an array + spaces := strings.Repeat(" ", indention-2) + if strings.HasPrefix(line, "apiGroups") { + // spaces + array start + out.WriteString(spaces + "- " + line + "\n") + } else { + // 2 more spaces + out.WriteString(spaces + " " + line + "\n") + } + } + } + return out.String() +} + +func getKubeVirtLogo(path string) string { + file, err := os.Open(path) + if err != nil { + panic(err) + } + + // Read entire file into byte slice. + reader := bufio.NewReader(file) + content, err := ioutil.ReadAll(reader) + if err != nil { + panic(err) + } + + // Encode as base64. + encoded := base64.StdEncoding.EncodeToString(content) + return encoded +} diff --git a/tools/resource-generator/resource-generator.go b/tools/resource-generator/resource-generator.go index 14294fc47fdc..8f0ad12f5ced 100644 --- a/tools/resource-generator/resource-generator.go +++ b/tools/resource-generator/resource-generator.go @@ -58,15 +58,24 @@ func main() { util.MarshallObject(components.NewKubeVirtCrd(), os.Stdout) case "kv-cr": util.MarshallObject(components.NewKubeVirtCR(*namespace, imagePullPolicy), os.Stdout) - case "rbac": + case "kubevirt-rbac": all := make([]interface{}, 0) - all = append(all, rbac.GetAllCluster(*namespace)...) all = append(all, rbac.GetAllApiServer(*namespace)...) all = append(all, rbac.GetAllController(*namespace)...) all = append(all, rbac.GetAllHandler(*namespace)...) for _, r := range all { util.MarshallObject(r, os.Stdout) } + case "cluster-rbac": + all := rbac.GetAllCluster(*namespace) + for _, r := range all { + util.MarshallObject(r, os.Stdout) + } + case "operator-rbac": + all := rbac.GetAllOperator(*namespace) + for _, r := range all { + util.MarshallObject(r, os.Stdout) + } case "prometheus": util.MarshallObject(components.NewPrometheusService(*namespace), os.Stdout) case "virt-api": @@ -93,6 +102,13 @@ func main() { panic(fmt.Errorf("error generating virt-handler deployment %v", err)) } util.MarshallObject(handler, os.Stdout) + case "virt-operator": + operator, err := components.NewOperatorDeployment(*namespace, *repository, *version, imagePullPolicy, *verbosity) + if err != nil { + panic(fmt.Errorf("error generating virt-operator deployment %v", err)) + + } + util.MarshallObject(operator, os.Stdout) default: panic(fmt.Errorf("unknown resource type %s", *resourceType)) } diff --git a/tools/util/marshaller.go b/tools/util/marshaller.go index afe78c2b6fbe..750602a3b48b 100644 --- a/tools/util/marshaller.go +++ b/tools/util/marshaller.go @@ -89,10 +89,15 @@ func MarshallObject(obj interface{}, writer io.Writer) error { return err } - // fix templates by removing quotes... + // fix templates by removing unneeded single quotes... s := string(yamlBytes) s = strings.Replace(s, "'{{", "{{", -1) s = strings.Replace(s, "}}'", "}}", -1) + + // fix double quoted strings by removing unneeded single quotes... + s = strings.Replace(s, " '\"", " \"", -1) + s = strings.Replace(s, "\"'\n", "\"\n", -1) + yamlBytes = []byte(s) _, err = writer.Write([]byte("---\n")) diff --git a/tools/vms-generator/utils/utils.go b/tools/vms-generator/utils/utils.go index e06afb08786a..6ab5a0f2dbaa 100644 --- a/tools/vms-generator/utils/utils.go +++ b/tools/vms-generator/utils/utils.go @@ -72,8 +72,6 @@ const VmiPresetSmall = "vmi-preset-small" const VmiMigration = "migration-job" -const KubeVirt = "kubevirt-cr" - const ( busVirtio = "virtio" busSata = "sata" @@ -87,8 +85,6 @@ const ( const windowsFirmware = "5d307ca9-b3ef-428c-8861-06e72d69f223" -const apiVersion = "kubevirt.io/v1alpha3" - var DockerPrefix = "registry:5000/kubevirt" var DockerTag = "devel"