Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

operator: add image upgrade with env vars #1499

Merged
merged 3 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DEVEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ Check if the fields mentioned below in the [base CSV manifest file](deployments/
- metadata.annotations.containerImage
- metadata.annotations.createdAT

Check if [manager yaml file](deployments/operator/manager/manager.yaml) `spec.template.spec.containers.env` has correct sha256 digest for each plugin image.

Fork the [Community Operators](https://github.com/k8s-operatorhub/community-operators) repo and clone it:
```
$ git clone https://github.com/<GitHub Username>/community-operators
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
endif
BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL)
OLM_MANIFESTS = deployments/operator/manifests
BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(TAG) $(BUNDLE_METADATA_OPTS) --kustomize-dir $(OLM_MANIFESTS) --output-dir . --use-image-digests
BUNDLE_DIR = community-operators/operators/intel-device-plugins-operator/$(TAG)

TESTDATA_DIR = pkg/topology/testdata
Expand Down Expand Up @@ -120,7 +121,7 @@ bundle:
rm -rf $(BUNDLE_DIR)
mkdir -p $(BUNDLE_DIR)
$(OPERATOR_SDK) generate kustomize manifests -q --input-dir $(OLM_MANIFESTS) --output-dir $(OLM_MANIFESTS) --apis-dir pkg/apis
$(KUSTOMIZE) build $(OLM_MANIFESTS) | sed "s|intel-deviceplugin-operator:devel|intel-deviceplugin-operator:$(TAG)|" | $(OPERATOR_SDK) generate bundle -q --overwrite --kustomize-dir $(OLM_MANIFESTS) --version $(TAG) $(BUNDLE_METADATA_OPTS) --output-dir .
$(KUSTOMIZE) build $(OLM_MANIFESTS) | sed "s|intel-deviceplugin-operator:devel|intel-deviceplugin-operator:$(TAG)|" | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS)
# Remove unneeded resources
rm manifests/*service.yaml
rm manifests/*clusterrole.yaml
Expand Down
10 changes: 6 additions & 4 deletions cmd/operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,13 @@ The upgrade of the deployed plugins can be done by simply installing a new relea

The operator auto-upgrades operator-managed plugins (CR images and thus corresponding deployed daemonsets) to the current release of the operator.

During upgrade the tag in the image path is updated (e.g. docker.io/intel/intel-sgx-plugin:tag), but the rest of the path is left intact.
From `0.28.0` release, each version of the operator can have a set of images in `deployments/operator/manager/manager.yaml` as env variables.

No upgrade is done for:
- Non-operator managed deployments
- Operator deployments without numeric tags
When env variables are set for specific plugins (and their initcontainers), plugins are upgraded to the images set as env variables and all user input is ignored.

The name of env variables is capitalized image with '_SHA' ending (e.g. in case of the image for `intel-sgx-plugin`, the env variable is `INTEL_SGX_PLUGIN_SHA`).

The value of env variables is the full path of the image (e.g. `docker.io/intel/intel-sgx-plugin@sha256:<digest>`).

## Limiting Supported Devices

Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/dlb/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func (c *controller) CreateEmptyObject() client.Object {

func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool {
dp := obj.(*devicepluginv1.DlbDevicePlugin)
return controllers.UpgradeImages(&dp.Spec.Image, &dp.Spec.InitImage)
return controllers.UpgradeImages(ctx, &dp.Spec.Image, &dp.Spec.InitImage)
}

func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client) (int, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/dsa/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (c *controller) CreateEmptyObject() client.Object {

func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool {
dp := obj.(*devicepluginv1.DsaDevicePlugin)
return controllers.UpgradeImages(&dp.Spec.Image, &dp.Spec.InitImage)
return controllers.UpgradeImages(ctx, &dp.Spec.Image, &dp.Spec.InitImage)
}

func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client) (int, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/fpga/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (c *controller) CreateEmptyObject() client.Object {

func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool {
dp := obj.(*devicepluginv1.FpgaDevicePlugin)
return controllers.UpgradeImages(&dp.Spec.Image, &dp.Spec.InitImage)
return controllers.UpgradeImages(ctx, &dp.Spec.Image, &dp.Spec.InitImage)
}

func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client) (int, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/gpu/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (c *controller) CreateEmptyObject() client.Object {

func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool {
dp := obj.(*devicepluginv1.GpuDevicePlugin)
return controllers.UpgradeImages(&dp.Spec.Image, &dp.Spec.InitImage)
return controllers.UpgradeImages(ctx, &dp.Spec.Image, &dp.Spec.InitImage)
}

func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client) (int, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/iaa/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (c *controller) CreateEmptyObject() client.Object {

func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool {
dp := obj.(*devicepluginv1.IaaDevicePlugin)
return controllers.UpgradeImages(&dp.Spec.Image, &dp.Spec.InitImage)
return controllers.UpgradeImages(ctx, &dp.Spec.Image, &dp.Spec.InitImage)
}

func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client) (int, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/qat/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (c *controller) CreateEmptyObject() client.Object {

func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool {
dp := obj.(*devicepluginv1.QatDevicePlugin)
return controllers.UpgradeImages(&dp.Spec.Image, &dp.Spec.InitImage)
return controllers.UpgradeImages(ctx, &dp.Spec.Image, &dp.Spec.InitImage)
}

func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client) (int, error) {
Expand Down
16 changes: 15 additions & 1 deletion pkg/controllers/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ package controllers

import (
"context"
"os"
"path/filepath"
"strings"
"sync"

Expand Down Expand Up @@ -167,14 +169,26 @@ func (r *reconciler) createObjects(ctx context.Context,
return result, nil
}

func UpgradeImages(image *string, initimage *string) (upgrade bool) {
func UpgradeImages(ctx context.Context, image *string, initimage *string) (upgrade bool) {
for _, s := range []*string{image, initimage} {
if s == nil {
continue
}

if parts := strings.SplitN(*s, ":", 2); len(parts) == 2 && len(parts[0]) > 0 {
name, version := parts[0], parts[1]

envVarValue := os.Getenv(strings.ReplaceAll(strings.ToUpper(filepath.Base(name)), "-", "_") + "_SHA")

if envVarValue != "" && *s != envVarValue {
mythi marked this conversation as resolved.
Show resolved Hide resolved
tkatila marked this conversation as resolved.
Show resolved Hide resolved
log.FromContext(ctx).Info("env var for the image: " + name + " is already set; user input of the image is ignored")

*s = envVarValue
upgrade = true

continue
}

if ver, err := versionutil.ParseSemantic(version); err == nil && ver.LessThan(ImageMinVersion) {
*s = name + ":" + ImageMinVersion.String()
upgrade = true
Expand Down
3 changes: 2 additions & 1 deletion pkg/controllers/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package controllers

import (
"context"
"testing"
)

Expand Down Expand Up @@ -63,7 +64,7 @@ func TestUpgrade(test *testing.T) {
for i := range tests {
t := tests[i]

upgrade := UpgradeImages(&t.image, &t.initimage)
upgrade := UpgradeImages(context.Background(), &t.image, &t.initimage)

if !(upgrade == t.upgrade && t.image == t.expectedImage && t.initimage == t.expectedInitimage) {
test.Errorf("expectedUpgrade: %v, received: %v", t.upgrade, upgrade)
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/sgx/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type controller struct {

func (c *controller) Upgrade(ctx context.Context, obj client.Object) bool {
dp := obj.(*devicepluginv1.SgxDevicePlugin)
return controllers.UpgradeImages(&dp.Spec.Image, &dp.Spec.InitImage)
return controllers.UpgradeImages(ctx, &dp.Spec.Image, &dp.Spec.InitImage)
}

func (c *controller) CreateEmptyObject() client.Object {
Expand Down
Loading