feat: set RELATED_IMAGES images to image puller spec as defaults

Signed-off-by: David Kwon <dakwon@redhat.com>
pull/923/head
David Kwon 2021-07-09 10:16:49 -04:00 committed by Ilya Buziuk
parent 78e5dbaa0c
commit cab8b92213
10 changed files with 213 additions and 36 deletions

View File

@ -358,16 +358,17 @@ spec:
description: Kubernetes Image Puller configuration
properties:
enable:
description: "Install and configure the Community Supported Kubernetes
description: Install and configure the Community Supported Kubernetes
Image Puller Operator. When set to `true` and no spec is provided,
it will create a default KubernetesImagePuller object to be managed
by the Operator. When set to `false`, the KubernetesImagePuller
object will be deleted, and the Operator will be uninstalled,
regardless of whether a spec is provided.
Note that while this
the Operator and its behavior is community-supported, its payload
may be commercially-supported for pulling commercially-supported
images."
regardless of whether a spec is provided. If the `spec.images`
field is empty, a set of recommended workspace-related images
will be automatically detected and pre-pulled after installation.
Note that while this Operator and its behavior is community-supported,
its payload may be commercially-supported for pulling commercially-supported
images.
type: boolean
spec:
description: A KubernetesImagePullerSpec to configure the image
@ -390,6 +391,9 @@ spec:
deploymentName:
type: string
images:
description: If empty, a set of recommended workspace-related
images will be automatically detected and pre-pulled after
installation.
type: string
nodeSelector:
type: string

View File

@ -364,16 +364,17 @@ spec:
description: Kubernetes Image Puller configuration
properties:
enable:
description: "Install and configure the Community Supported Kubernetes
description: Install and configure the Community Supported Kubernetes
Image Puller Operator. When set to `true` and no spec is provided,
it will create a default KubernetesImagePuller object to be
managed by the Operator. When set to `false`, the KubernetesImagePuller
object will be deleted, and the Operator will be uninstalled,
regardless of whether a spec is provided.
Note that while
this the Operator and its behavior is community-supported, its
payload may be commercially-supported for pulling commercially-supported
images."
regardless of whether a spec is provided. If the `spec.images`
field is empty, a set of recommended workspace-related images
will be automatically detected and pre-pulled after installation.
Note that while this Operator and its behavior is community-supported,
its payload may be commercially-supported for pulling commercially-supported
images.
type: boolean
spec:
description: A KubernetesImagePullerSpec to configure the image
@ -396,6 +397,9 @@ spec:
deploymentName:
type: string
images:
description: If empty, a set of recommended workspace-related
images will be automatically detected and pre-pulled after
installation.
type: string
nodeSelector:
type: string

View File

@ -86,13 +86,13 @@ metadata:
categories: Developer Tools
certified: "false"
containerImage: quay.io/eclipse/che-operator:next
createdAt: "2021-07-07T09:30:36Z"
createdAt: "2021-07-12T13:17:30Z"
description: A Kube-native development solution that delivers portable and collaborative
developer workspaces.
operatorframework.io/suggested-namespace: eclipse-che
repository: https://github.com/eclipse-che/che-operator
support: Eclipse Foundation
name: eclipse-che-preview-kubernetes.v7.33.0-250.nightly
name: eclipse-che-preview-kubernetes.v7.33.0-252.nightly
namespace: placeholder
spec:
apiservicedefinitions: {}
@ -1241,4 +1241,4 @@ spec:
maturity: stable
provider:
name: Eclipse Foundation
version: 7.33.0-250.nightly
version: 7.33.0-252.nightly

View File

@ -364,16 +364,17 @@ spec:
description: Kubernetes Image Puller configuration
properties:
enable:
description: "Install and configure the Community Supported Kubernetes
description: Install and configure the Community Supported Kubernetes
Image Puller Operator. When set to `true` and no spec is provided,
it will create a default KubernetesImagePuller object to be
managed by the Operator. When set to `false`, the KubernetesImagePuller
object will be deleted, and the Operator will be uninstalled,
regardless of whether a spec is provided.
Note that while
this the Operator and its behavior is community-supported, its
payload may be commercially-supported for pulling commercially-supported
images."
regardless of whether a spec is provided. If the `spec.images`
field is empty, a set of recommended workspace-related images
will be automatically detected and pre-pulled after installation.
Note that while this Operator and its behavior is community-supported,
its payload may be commercially-supported for pulling commercially-supported
images.
type: boolean
spec:
description: A KubernetesImagePullerSpec to configure the image
@ -396,6 +397,9 @@ spec:
deploymentName:
type: string
images:
description: If empty, a set of recommended workspace-related
images will be automatically detected and pre-pulled after
installation.
type: string
nodeSelector:
type: string

View File

@ -77,13 +77,13 @@ metadata:
categories: Developer Tools, OpenShift Optional
certified: "false"
containerImage: quay.io/eclipse/che-operator:next
createdAt: "2021-07-07T09:30:48Z"
createdAt: "2021-07-12T13:17:47Z"
description: A Kube-native development solution that delivers portable and collaborative
developer workspaces in OpenShift.
operatorframework.io/suggested-namespace: eclipse-che
repository: https://github.com/eclipse-che/che-operator
support: Eclipse Foundation
name: eclipse-che-preview-openshift.v7.33.0-250.nightly
name: eclipse-che-preview-openshift.v7.33.0-252.nightly
namespace: placeholder
spec:
apiservicedefinitions: {}
@ -1318,4 +1318,4 @@ spec:
maturity: stable
provider:
name: Eclipse Foundation
version: 7.33.0-250.nightly
version: 7.33.0-252.nightly

View File

@ -370,15 +370,17 @@ spec:
description: Kubernetes Image Puller configuration
properties:
enable:
description: "Install and configure the Community Supported\
\ Kubernetes Image Puller Operator. When set to `true` and\
\ no spec is provided, it will create a default KubernetesImagePuller\
\ object to be managed by the Operator. When set to `false`,\
\ the KubernetesImagePuller object will be deleted, and the\
\ Operator will be uninstalled, regardless of whether a spec\
\ is provided. Note that while this the Operator and its behavior\
\ is community-supported, its payload may be commercially-supported\
\ for pulling commercially-supported images."
description: Install and configure the Community Supported Kubernetes
Image Puller Operator. When set to `true` and no spec is provided,
it will create a default KubernetesImagePuller object to be
managed by the Operator. When set to `false`, the KubernetesImagePuller
object will be deleted, and the Operator will be uninstalled,
regardless of whether a spec is provided. If the `spec.images`
field is empty, a set of recommended workspace-related images
will be automatically detected and pre-pulled after installation.
Note that while this Operator and its behavior is community-supported,
its payload may be commercially-supported for pulling commercially-supported
images.
type: boolean
spec:
description: A KubernetesImagePullerSpec to configure the image
@ -401,6 +403,9 @@ spec:
deploymentName:
type: string
images:
description: If empty, a set of recommended workspace-related
images will be automatically detected and pre-pulled after
installation.
type: string
nodeSelector:
type: string

View File

@ -592,8 +592,9 @@ type CheClusterSpecImagePuller struct {
// it will create a default KubernetesImagePuller object to be managed by the Operator.
// When set to `false`, the KubernetesImagePuller object will be deleted, and the Operator will be uninstalled,
// regardless of whether a spec is provided.
//
// Note that while this the Operator and its behavior is community-supported, its payload may be commercially-supported
// If the `spec.images` field is empty, a set of recommended workspace-related images will be automatically detected and
// pre-pulled after installation.
// Note that while this Operator and its behavior is community-supported, its payload may be commercially-supported
// for pulling commercially-supported images.
Enable bool `json:"enable"`
// A KubernetesImagePullerSpec to configure the image puller in the CheCluster
@ -748,3 +749,7 @@ func (c *CheCluster) IsAirGapMode() bool {
func (c *CheCluster) IsImagePullerSpecEmpty() bool {
return c.Spec.ImagePuller.Spec == (chev1alpha1.KubernetesImagePullerSpec{})
}
func (c *CheCluster) IsImagePullerImagesEmpty() bool {
return len(c.Spec.ImagePuller.Spec.Images) == 0
}

View File

@ -148,6 +148,7 @@ var (
Spec: chev1alpha1.KubernetesImagePullerSpec{
DeploymentName: "kubernetes-image-puller",
ConfigMapName: "k8s-image-puller",
Images: "che-workspace-plugin-broker-metadata=quay.io/eclipse/che-plugin-metadata-broker:v3.4.0;che-workspace-plugin-broker-artifacts=quay.io/eclipse/che-plugin-artifacts-broker:v3.4.0;",
},
}
clusterServiceVersion = &operatorsv1alpha1.ClusterServiceVersion{
@ -731,6 +732,45 @@ func TestImagePullerConfiguration(t *testing.T) {
},
expectedImagePuller: defaultImagePuller,
},
{
name: "image puller enabled, user images set, subscription exists, should create a KubernetesImagePuller with user images",
initCR: InitCheCRWithImagePullerEnabledAndImagesSet(),
initObjects: []runtime.Object{
packageManifest,
operatorGroup,
subscription,
},
expectedImagePuller: &chev1alpha1.KubernetesImagePuller{
TypeMeta: metav1.TypeMeta{
APIVersion: "che.eclipse.org/v1alpha1",
Kind: "KubernetesImagePuller",
},
ObjectMeta: metav1.ObjectMeta{
Name: "eclipse-che-image-puller",
Namespace: namespace,
Labels: map[string]string{
"app.kubernetes.io/part-of": name,
"app": "che",
"component": "kubernetes-image-puller",
},
ResourceVersion: "1",
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: "org.eclipse.che/v1",
Kind: "CheCluster",
Controller: &valueTrue,
BlockOwnerDeletion: &valueTrue,
Name: "eclipse-che",
},
},
},
Spec: chev1alpha1.KubernetesImagePullerSpec{
DeploymentName: "kubernetes-image-puller",
ConfigMapName: "k8s-image-puller",
Images: "image=image_url",
},
},
},
{
name: "image puller enabled, KubernetesImagePuller created and spec in CheCluster is different, should update the KubernetesImagePuller",
initCR: InitCheCRWithImagePullerEnabledAndNewValuesSet(),
@ -1541,6 +1581,31 @@ func InitCheCRWithImagePullerEnabledAndDefaultValuesSet() *orgv1.CheCluster {
}
}
func InitCheCRWithImagePullerEnabledAndImagesSet() *orgv1.CheCluster {
return &orgv1.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Finalizers: []string{
"kubernetesimagepullers.finalizers.che.eclipse.org",
},
},
Spec: orgv1.CheClusterSpec{
ImagePuller: orgv1.CheClusterSpecImagePuller{
Enable: true,
Spec: chev1alpha1.KubernetesImagePullerSpec{
DeploymentName: "kubernetes-image-puller",
ConfigMapName: "k8s-image-puller",
Images: "image=image_url",
},
},
Auth: orgv1.CheClusterSpecAuth{
OpenShiftoAuth: util.NewBoolPointer(false),
},
},
}
}
func InitCheCRWithImagePullerEnabledAndNewValuesSet() *orgv1.CheCluster {
return &orgv1.CheCluster{
ObjectMeta: metav1.ObjectMeta{

View File

@ -13,6 +13,8 @@ package deploy
import (
"context"
goerror "errors"
"strings"
"time"
chev1alpha1 "github.com/che-incubator/kubernetes-image-puller-operator/pkg/apis/che/v1alpha1"
@ -22,9 +24,11 @@ import (
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
packagesv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators/v1"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)
@ -127,6 +131,13 @@ func ReconcileImagePuller(ctx *DeployContext) (reconcile.Result, error) {
return reconcile.Result{Requeue: true}, nil
}
if ctx.CheCluster.IsImagePullerImagesEmpty() {
if err = AddDefaultImages(ctx); err != nil {
logrus.Error(err)
return reconcile.Result{}, err
}
}
logrus.Infof("Creating KubernetesImagePuller for CheCluster %v", ctx.CheCluster.Name)
createdImagePuller, err := CreateKubernetesImagePuller(ctx)
if err != nil {
@ -386,6 +397,83 @@ func UpdateImagePullerSpecIfEmpty(ctx *DeployContext) (orgv1.CheClusterSpecImage
return ctx.CheCluster.Spec.ImagePuller, nil
}
func AddDefaultImages(ctx *DeployContext) error {
defaultImageVars := GetDefaultImagesEnvVars()
if len(defaultImageVars) == 0 {
return nil
}
defaultImages := ""
for _, envVar := range defaultImageVars {
defaultImages += envVar.Name + "=" + envVar.Value + ";"
}
ctx.CheCluster.Spec.ImagePuller.Spec.Images = defaultImages
return UpdateCheCRSpec(ctx, "Kubernetes Image Puller default images", defaultImages)
}
func GetDefaultImagesEnvVars() []v1.EnvVar {
imagePatterns := [...]string{
"^RELATED_IMAGE_.*_plugin_java8$",
"^RELATED_IMAGE_.*_plugin_java11$",
"^RELATED_IMAGE_.*_plugin_kubernetes$",
"^RELATED_IMAGE_.*_plugin_openshift$",
"^RELATED_IMAGE_.*_plugin_broker.*",
"^RELATED_IMAGE_.*_theia.*",
"^RELATED_IMAGE_.*_stacks_cpp$",
"^RELATED_IMAGE_.*_stacks_dotnet$",
"^RELATED_IMAGE_.*_stacks_golang$",
"^RELATED_IMAGE_.*_stacks_php$",
"^RELATED_IMAGE_.*_cpp_.*_devfile_registry_image.*",
"^RELATED_IMAGE_.*_dotnet_.*_devfile_registry_image.*",
"^RELATED_IMAGE_.*_golang_.*_devfile_registry_image.*",
"^RELATED_IMAGE_.*_php_.*_devfile_registry_image.*",
"^RELATED_IMAGE_.*_java.*_maven_devfile_registry_image.*",
}
var err error
imageVars := []v1.EnvVar{}
for _, pattern := range imagePatterns {
matches := util.GetEnvByRegExp(pattern)
for _, match := range matches {
match.Name = match.Name[len("RELATED_IMAGE_"):]
match.Name, err = ConvertToRFC1123(match.Name)
if err != nil {
logrus.Errorf(err.Error())
continue
}
imageVars = append(imageVars, match)
}
}
return imageVars
}
// Convert input string to RFC 1123 format ([a-z0-9]([-a-z0-9]*[a-z0-9])?) max 63 characters, if possible
func ConvertToRFC1123(str string) (string, error) {
result := strings.ToLower(str)
if len(str) > validation.DNS1123LabelMaxLength {
result = result[:validation.DNS1123LabelMaxLength]
}
// Remove illegal trailing characters
i := len(result) - 1
for i >= 0 && !IsRFC1123Char(result[i]) {
i -= 1
}
result = result[:i+1]
result = strings.ReplaceAll(result, "_", "-")
if errs := validation.IsDNS1123Label(result); len(errs) > 0 {
return "", goerror.New("Cannot convert the following string to RFC 1123 format: " + str)
}
return result, nil
}
func IsRFC1123Char(ch byte) bool {
errs := validation.IsDNS1123Label(string(ch))
return len(errs) == 0
}
func CreateKubernetesImagePuller(ctx *DeployContext) (bool, error) {
imagePuller := GetExpectedKubernetesImagePuller(ctx)
err := ctx.ClusterAPI.Client.Create(context.TODO(), imagePuller, &client.CreateOptions{})

View File

@ -8,12 +8,14 @@ import (
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// +k8s:openapi-gen=true
// KubernetesImagePullerSpec defines the desired state of KubernetesImagePuller
type KubernetesImagePullerSpec struct {
// If empty, a set of recommended workspace-related images will be automatically detected and pre-pulled after installation.
Images string `json:"images,omitempty"`
ConfigMapName string `json:"configMapName,omitempty"`
DaemonsetName string `json:"daemonsetName,omitempty"`
DeploymentName string `json:"deploymentName,omitempty"`
Images string `json:"images,omitempty"`
CachingIntervalHours string `json:"cachingIntervalHours,omitempty"`
CachingMemoryRequest string `json:"cachingMemoryRequest,omitempty"`
CachingMemoryLimit string `json:"cachingMemoryLimit,omitempty"`