mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-02-14 18:09:57 +00:00
support set imagepullsecret credential in helm chart and run e2e using helm chart (#605)
Signed-off-by: Zhiwei Yin <zyin@redhat.com>
This commit is contained in:
146
pkg/operator/helpers/chart/config.go
Normal file
146
pkg/operator/helpers/chart/config.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package chart
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
operatorv1 "open-cluster-management.io/api/operator/v1"
|
||||
)
|
||||
|
||||
type ClusterManagerChartConfig struct {
|
||||
// CreateNamespace is used in the render function to append the release ns in the objects.
|
||||
CreateNamespace bool `json:"createNamespace,omitempty"`
|
||||
// ReplicaCount is the replicas for the clusterManager operator deployment.
|
||||
ReplicaCount int `json:"replicaCount,omitempty"`
|
||||
// Images is the configurations for all images used in operator deployment and clusterManager CR.
|
||||
Images ImagesConfig `json:"images,omitempty"`
|
||||
// PodSecurityContext is the pod SecurityContext in the operator deployment
|
||||
PodSecurityContext corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
|
||||
// SecurityContext is the container SecurityContext in operator deployment
|
||||
SecurityContext corev1.SecurityContext `json:"securityContext,omitempty"`
|
||||
// Resources is the resource requirements of the operator deployment
|
||||
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
|
||||
// NodeSelector is the nodeSelector of the operator deployment
|
||||
NodeSelector corev1.NodeSelector `json:"nodeSelector,omitempty"`
|
||||
// Tolerations is the tolerations of the operator deployment
|
||||
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
|
||||
// Affinity is the affinity of the operator deployment
|
||||
Affinity corev1.Affinity `json:"affinity,omitempty"`
|
||||
// CreateBootstrapToken is to enable/disable the bootstrap token secret for auto approve.
|
||||
CreateBootstrapToken bool `json:"createBootstrapToken,omitempty"`
|
||||
// CreateBootstrapSA is to create a serviceAccount to generate token.
|
||||
CreateBootstrapSA bool `json:"createBootstrapSA,omitempty"`
|
||||
// ClusterManager is the configuration of clusterManager CR
|
||||
ClusterManager ClusterManagerConfig `json:"clusterManager,omitempty"`
|
||||
}
|
||||
|
||||
type KlusterletChartConfig struct {
|
||||
// CreateNamespace is used in the render function to append the release ns in the objects.
|
||||
CreateNamespace bool `json:"createNamespace,omitempty"`
|
||||
// ReplicaCount is the replicas for the klusterlet operator deployment.
|
||||
ReplicaCount int `json:"replicaCount,omitempty"`
|
||||
// Images is the configurations for all images used in operator deployment and klusterlet CR.
|
||||
Images ImagesConfig `json:"images,omitempty"`
|
||||
// PodSecurityContext is the pod SecurityContext in the operator deployment
|
||||
PodSecurityContext corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`
|
||||
// SecurityContext is the container SecurityContext in operator deployment
|
||||
SecurityContext corev1.SecurityContext `json:"securityContext,omitempty"`
|
||||
// Resources is the resource requirements of the operator deployment
|
||||
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
|
||||
// NodeSelector is the nodeSelector of the operator deployment
|
||||
NodeSelector corev1.NodeSelector `json:"nodeSelector,omitempty"`
|
||||
// Tolerations is the tolerations of the operator deployment
|
||||
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
|
||||
// Affinity is the affinity of the operator deployment
|
||||
Affinity corev1.Affinity `json:"affinity,omitempty"`
|
||||
// Klusterlet is the configuration of klusterlet CR
|
||||
Klusterlet KlusterletConfig `json:"klusterlet,omitempty"`
|
||||
// PriorityClassName is the name of the PriorityClass that will be used by the deployed klusterlet agent and operator.
|
||||
PriorityClassName string `json:"priorityClassName,omitempty"`
|
||||
|
||||
// EnableSyncLabels is to enable the feature which can sync the labels from klusterlet to all agent resources.
|
||||
EnableSyncLabels bool `json:"enableSyncLabels,omitempty"`
|
||||
|
||||
// BootstrapHubKubeConfig should be the kubeConfig file of the hub cluster via setting --set-file=<the kubeConfig file of hub cluster> optional
|
||||
BootstrapHubKubeConfig string `json:"bootstrapHubKubeConfig,omitempty"`
|
||||
|
||||
// ExternalManagedKubeConfig should be the kubeConfig file of the managed cluster via setting --set-file=<the kubeConfig file of managed cluster>
|
||||
// only need to set in the hosted mode. optional
|
||||
ExternalManagedKubeConfig string `json:"externalManagedKubeConfig,omitempty"`
|
||||
|
||||
// NoOperator is to only deploy the klusterlet CR if set true.
|
||||
NoOperator bool `json:"noOperator,omitempty"`
|
||||
}
|
||||
|
||||
type ImagesConfig struct {
|
||||
// Registry is registry name must NOT contain a trailing slash.
|
||||
Registry string `json:"registry,omitempty"`
|
||||
// Tag is the operator image tag.
|
||||
Tag string `json:"tag,omitempty"`
|
||||
// ImagePullPolicy is the image pull policy of operator image. Default is IfNotPresent.
|
||||
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
|
||||
// The image pull secret name is open-cluster-management-image-pull-credentials.
|
||||
// Please set the userName and password if you use a private image registry.
|
||||
ImageCredentials ImageCredentials `json:"imageCredentials,omitempty"`
|
||||
}
|
||||
|
||||
type ImageCredentials struct {
|
||||
CreateImageCredentials bool `json:"createImageCredentials,omitempty"`
|
||||
UserName string `json:"userName,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
DockerConfigJson string `json:"dockerConfigJson,omitempty"`
|
||||
}
|
||||
|
||||
type ClusterManagerConfig struct {
|
||||
// Create determines if create the clusterManager CR, default is true.
|
||||
Create bool `json:"create,omitempty"`
|
||||
// InstallMode represents the mode of deploy cluster-manager
|
||||
Mode operatorv1.InstallMode `json:"mode,omitempty"`
|
||||
|
||||
// RegistrationConfiguration contains the configuration of registration
|
||||
// +optional
|
||||
RegistrationConfiguration operatorv1.RegistrationHubConfiguration `json:"registrationConfiguration,omitempty"`
|
||||
|
||||
// WorkConfiguration contains the configuration of work
|
||||
// +optional
|
||||
WorkConfiguration operatorv1.WorkConfiguration `json:"workConfiguration,omitempty"`
|
||||
|
||||
// AddOnManagerConfiguration contains the configuration of addon manager
|
||||
// +optional
|
||||
AddOnManagerConfiguration operatorv1.AddOnManagerConfiguration `json:"addOnManagerConfiguration,omitempty"`
|
||||
|
||||
// ResourceRequirement specify QoS classes of deployments managed by clustermanager.
|
||||
// It applies to all the containers in the deployments.
|
||||
// +optional
|
||||
ResourceRequirement operatorv1.ResourceRequirement `json:"resourceRequirement,omitempty"`
|
||||
}
|
||||
|
||||
type KlusterletConfig struct {
|
||||
// Create determines if create the klusterlet CR, default is true.
|
||||
Create bool `json:"create,omitempty"`
|
||||
// InstallMode represents the mode of deploy klusterlet
|
||||
Mode operatorv1.InstallMode `json:"mode,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ClusterName string `json:"clusterName,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
// ExternalServerURLs represents a list of apiserver urls and ca bundles that is accessible externally
|
||||
// If it is set empty, managed cluster has no externally accessible url that hub cluster can visit.
|
||||
// +optional
|
||||
ExternalServerURLs []operatorv1.ServerURL `json:"externalServerURLs,omitempty"`
|
||||
|
||||
// NodePlacement enables explicit control over the scheduling of the deployed pods.
|
||||
// +optional
|
||||
NodePlacement operatorv1.NodePlacement `json:"nodePlacement,omitempty"`
|
||||
|
||||
// RegistrationConfiguration contains the configuration of registration
|
||||
// +optional
|
||||
RegistrationConfiguration operatorv1.RegistrationConfiguration `json:"registrationConfiguration,omitempty"`
|
||||
|
||||
// WorkConfiguration contains the configuration of work
|
||||
// +optional
|
||||
WorkConfiguration operatorv1.WorkAgentConfiguration `json:"workConfiguration,omitempty"`
|
||||
|
||||
// ResourceRequirement specify QoS classes of deployments managed by clustermanager.
|
||||
// It applies to all the containers in the deployments.
|
||||
// +optional
|
||||
ResourceRequirement operatorv1.ResourceRequirement `json:"resourceRequirement,omitempty"`
|
||||
}
|
||||
@@ -22,20 +22,26 @@ import (
|
||||
klusterletchart "open-cluster-management.io/ocm/deploy/klusterlet/chart"
|
||||
)
|
||||
|
||||
func NewDefaultClusterManagerChartConfig() *clustermanagerchart.ChartConfig {
|
||||
return &clustermanagerchart.ChartConfig{
|
||||
func NewDefaultClusterManagerChartConfig() *ClusterManagerChartConfig {
|
||||
return &ClusterManagerChartConfig{
|
||||
ReplicaCount: 3,
|
||||
CreateBootstrapToken: false,
|
||||
ClusterManager: ClusterManagerConfig{
|
||||
Create: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDefaultKlusterletChartConfig() *klusterletchart.ChartConfig {
|
||||
return &klusterletchart.ChartConfig{
|
||||
func NewDefaultKlusterletChartConfig() *KlusterletChartConfig {
|
||||
return &KlusterletChartConfig{
|
||||
ReplicaCount: 3,
|
||||
Klusterlet: KlusterletConfig{
|
||||
Create: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func RenderClusterManagerChart(config *clustermanagerchart.ChartConfig, namespace string) ([][]byte, error) {
|
||||
func RenderClusterManagerChart(config *ClusterManagerChartConfig, namespace string) ([][]byte, error) {
|
||||
if namespace == "" {
|
||||
return nil, fmt.Errorf("cluster manager chart namespace is required")
|
||||
}
|
||||
@@ -43,7 +49,7 @@ func RenderClusterManagerChart(config *clustermanagerchart.ChartConfig, namespac
|
||||
clustermanagerchart.ChartName, clustermanagerchart.ChartFiles)
|
||||
}
|
||||
|
||||
func RenderKlusterletChart(config *klusterletchart.ChartConfig, namespace string) ([][]byte, error) {
|
||||
func RenderKlusterletChart(config *KlusterletChartConfig, namespace string) ([][]byte, error) {
|
||||
if namespace == "" {
|
||||
return nil, fmt.Errorf("klusterlet chart namespace is required")
|
||||
}
|
||||
@@ -51,7 +57,7 @@ func RenderKlusterletChart(config *klusterletchart.ChartConfig, namespace string
|
||||
klusterletchart.ChartName, klusterletchart.ChartFiles)
|
||||
}
|
||||
|
||||
func renderChart[T *clustermanagerchart.ChartConfig | *klusterletchart.ChartConfig](config T,
|
||||
func renderChart[T *ClusterManagerChartConfig | *KlusterletChartConfig](config T,
|
||||
namespace string, createNamespace bool, chartName string, fs embed.FS) ([][]byte, error) {
|
||||
// chartName is the prefix of chart path here
|
||||
operatorChart, err := LoadChart(fs, chartName)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package chart
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
@@ -14,9 +15,6 @@ import (
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
|
||||
operatorv1 "open-cluster-management.io/api/operator/v1"
|
||||
|
||||
clustermanagerchart "open-cluster-management.io/ocm/deploy/cluster-manager/chart"
|
||||
klusterletchart "open-cluster-management.io/ocm/deploy/klusterlet/chart"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -42,13 +40,13 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
namespace string
|
||||
chartConfig func() *clustermanagerchart.ChartConfig
|
||||
chartConfig func() *ClusterManagerChartConfig
|
||||
expectedObjCnt int
|
||||
}{
|
||||
{
|
||||
name: "default config",
|
||||
namespace: "open-cluster-management",
|
||||
chartConfig: func() *clustermanagerchart.ChartConfig {
|
||||
chartConfig: func() *ClusterManagerChartConfig {
|
||||
config := NewDefaultClusterManagerChartConfig()
|
||||
return config
|
||||
},
|
||||
@@ -57,7 +55,7 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
{
|
||||
name: "enable bootstrap token",
|
||||
namespace: "multicluster-engine",
|
||||
chartConfig: func() *clustermanagerchart.ChartConfig {
|
||||
chartConfig: func() *ClusterManagerChartConfig {
|
||||
config := NewDefaultClusterManagerChartConfig()
|
||||
config.CreateBootstrapToken = true
|
||||
return config
|
||||
@@ -67,7 +65,7 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
{
|
||||
name: "enable bootstrap sa",
|
||||
namespace: "multicluster-engine",
|
||||
chartConfig: func() *clustermanagerchart.ChartConfig {
|
||||
chartConfig: func() *ClusterManagerChartConfig {
|
||||
config := NewDefaultClusterManagerChartConfig()
|
||||
config.CreateBootstrapSA = true
|
||||
return config
|
||||
@@ -77,13 +75,13 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
{
|
||||
name: "change images config",
|
||||
namespace: "ocm",
|
||||
chartConfig: func() *clustermanagerchart.ChartConfig {
|
||||
chartConfig: func() *ClusterManagerChartConfig {
|
||||
config := NewDefaultClusterManagerChartConfig()
|
||||
config.Images = clustermanagerchart.ImagesConfig{
|
||||
config.Images = ImagesConfig{
|
||||
Registry: "myrepo",
|
||||
Tag: "v9.9.9",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
ImageCredentials: clustermanagerchart.ImageCredentials{
|
||||
ImageCredentials: ImageCredentials{
|
||||
CreateImageCredentials: true,
|
||||
UserName: "test",
|
||||
Password: "test",
|
||||
@@ -93,10 +91,28 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
},
|
||||
expectedObjCnt: 7,
|
||||
},
|
||||
{
|
||||
name: "change images config dockerConfigJson",
|
||||
namespace: "ocm",
|
||||
chartConfig: func() *ClusterManagerChartConfig {
|
||||
config := NewDefaultClusterManagerChartConfig()
|
||||
config.Images = ImagesConfig{
|
||||
Registry: "myrepo",
|
||||
Tag: "v9.9.9",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
ImageCredentials: ImageCredentials{
|
||||
CreateImageCredentials: true,
|
||||
DockerConfigJson: `{"auths":{"quay.io":{"auth":"YWJjCg=="}}}`,
|
||||
},
|
||||
}
|
||||
return config
|
||||
},
|
||||
expectedObjCnt: 7,
|
||||
},
|
||||
{
|
||||
name: "create namespace",
|
||||
namespace: "multicluster-engine",
|
||||
chartConfig: func() *clustermanagerchart.ChartConfig {
|
||||
chartConfig: func() *ClusterManagerChartConfig {
|
||||
config := NewDefaultClusterManagerChartConfig()
|
||||
config.CreateBootstrapToken = true
|
||||
config.CreateNamespace = true
|
||||
@@ -163,6 +179,22 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
object.Spec.AddOnManagerImagePullSpec != fmt.Sprintf("%s/addon-manager:%s", registry, version) {
|
||||
t.Errorf("failed to render images")
|
||||
}
|
||||
case *corev1.Secret:
|
||||
switch object.Name {
|
||||
case "open-cluster-management-image-pull-credentials":
|
||||
data := object.Data[corev1.DockerConfigJsonKey]
|
||||
if len(data) == 0 {
|
||||
t.Errorf("failed to get image pull secret")
|
||||
}
|
||||
if base64.StdEncoding.EncodeToString(data) == "" {
|
||||
t.Errorf("failed to render image pull secret")
|
||||
}
|
||||
case "bootstrap-token-ocmhub":
|
||||
data := object.StringData["token-secret"]
|
||||
if len(data) != 16 {
|
||||
t.Errorf("failed to get token secret")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -173,13 +205,13 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
namespace string
|
||||
chartConfig func() *klusterletchart.ChartConfig
|
||||
chartConfig func() *KlusterletChartConfig
|
||||
expectedObjCnt int
|
||||
}{
|
||||
{
|
||||
name: "default config",
|
||||
namespace: "open-cluster-management",
|
||||
chartConfig: func() *klusterletchart.ChartConfig {
|
||||
chartConfig: func() *KlusterletChartConfig {
|
||||
config := NewDefaultKlusterletChartConfig()
|
||||
config.Klusterlet.ClusterName = "testCluster"
|
||||
config.Klusterlet.Mode = operatorv1.InstallModeSingleton
|
||||
@@ -190,7 +222,7 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
{
|
||||
name: "use bootstrapHubKubeConfig",
|
||||
namespace: "open-cluster-management",
|
||||
chartConfig: func() *klusterletchart.ChartConfig {
|
||||
chartConfig: func() *KlusterletChartConfig {
|
||||
config := NewDefaultKlusterletChartConfig()
|
||||
config.Klusterlet.ClusterName = "testCluster"
|
||||
config.Klusterlet.Mode = operatorv1.InstallModeSingleton
|
||||
@@ -203,13 +235,13 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
{
|
||||
name: "change images config",
|
||||
namespace: "ocm",
|
||||
chartConfig: func() *klusterletchart.ChartConfig {
|
||||
chartConfig: func() *KlusterletChartConfig {
|
||||
config := NewDefaultKlusterletChartConfig()
|
||||
config.Images = klusterletchart.ImagesConfig{
|
||||
config.Images = ImagesConfig{
|
||||
Registry: "myrepo",
|
||||
Tag: "v9.9.9",
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
ImageCredentials: klusterletchart.ImageCredentials{
|
||||
ImageCredentials: ImageCredentials{
|
||||
CreateImageCredentials: true,
|
||||
UserName: "test",
|
||||
Password: "test",
|
||||
@@ -224,7 +256,7 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
{
|
||||
name: "hosted mode",
|
||||
namespace: "ocm",
|
||||
chartConfig: func() *klusterletchart.ChartConfig {
|
||||
chartConfig: func() *KlusterletChartConfig {
|
||||
config := NewDefaultKlusterletChartConfig()
|
||||
config.NoOperator = true
|
||||
config.Klusterlet.Name = "klusterlet2"
|
||||
@@ -237,7 +269,7 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
{
|
||||
name: "noOperator",
|
||||
namespace: "ocm",
|
||||
chartConfig: func() *klusterletchart.ChartConfig {
|
||||
chartConfig: func() *KlusterletChartConfig {
|
||||
config := NewDefaultKlusterletChartConfig()
|
||||
config.NoOperator = true
|
||||
config.Klusterlet.Name = "klusterlet2"
|
||||
@@ -250,7 +282,7 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
{
|
||||
name: "create namespace",
|
||||
namespace: "open-cluster-management",
|
||||
chartConfig: func() *klusterletchart.ChartConfig {
|
||||
chartConfig: func() *KlusterletChartConfig {
|
||||
config := NewDefaultKlusterletChartConfig()
|
||||
config.Klusterlet.ClusterName = "testCluster"
|
||||
config.Klusterlet.Mode = operatorv1.InstallModeSingleton
|
||||
@@ -359,6 +391,22 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
fmt.Sprintf("open-cluster-management-%s", object.Spec.ClusterName), object.Spec.Namespace)
|
||||
}
|
||||
}
|
||||
case *corev1.Secret:
|
||||
switch object.Name {
|
||||
case "open-cluster-management-image-pull-credentials":
|
||||
data := object.Data[corev1.DockerConfigJsonKey]
|
||||
if len(data) == 0 {
|
||||
t.Errorf("failed to get image pull secret")
|
||||
}
|
||||
if base64.StdEncoding.EncodeToString(data) == "" {
|
||||
t.Errorf("failed to render image pull secret")
|
||||
}
|
||||
case "bootstrap-hub-kubeconfig", "external-managed-kubeconfig":
|
||||
data := object.Data["kubeconfig"]
|
||||
if base64.StdEncoding.EncodeToString(data) == "" {
|
||||
t.Errorf("failed to render kubeconfig")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user