mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-08-23 22:26:49 +00:00
add createNamespace option to chart render (#603)
Signed-off-by: Zhiwei Yin <zyin@redhat.com>
This commit is contained in:
@@ -17,6 +17,8 @@ var ChartFiles embed.FS
|
||||
const ChartName = "cluster-manager"
|
||||
|
||||
type ChartConfig 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.
|
||||
|
||||
@@ -17,6 +17,8 @@ var ChartFiles embed.FS
|
||||
const ChartName = "klusterlet"
|
||||
|
||||
type ChartConfig 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.
|
||||
|
||||
@@ -11,10 +11,12 @@ import (
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
"helm.sh/helm/v3/pkg/chartutil"
|
||||
"helm.sh/helm/v3/pkg/engine"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
clustermanagerchart "open-cluster-management.io/ocm/deploy/cluster-manager/chart"
|
||||
klusterletchart "open-cluster-management.io/ocm/deploy/klusterlet/chart"
|
||||
@@ -33,8 +35,24 @@ func NewDefaultKlusterletChartConfig() *klusterletchart.ChartConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func RenderChart[T *clustermanagerchart.ChartConfig | *klusterletchart.ChartConfig](config T,
|
||||
namespace string, chartName string, fs embed.FS) ([][]byte, error) {
|
||||
func RenderClusterManagerChart(config *clustermanagerchart.ChartConfig, namespace string) ([][]byte, error) {
|
||||
if namespace == "" {
|
||||
return nil, fmt.Errorf("cluster manager chart namespace is required")
|
||||
}
|
||||
return renderChart(config, namespace, config.CreateNamespace,
|
||||
clustermanagerchart.ChartName, clustermanagerchart.ChartFiles)
|
||||
}
|
||||
|
||||
func RenderKlusterletChart(config *klusterletchart.ChartConfig, namespace string) ([][]byte, error) {
|
||||
if namespace == "" {
|
||||
return nil, fmt.Errorf("klusterlet chart namespace is required")
|
||||
}
|
||||
return renderChart(config, namespace, config.CreateNamespace,
|
||||
klusterletchart.ChartName, klusterletchart.ChartFiles)
|
||||
}
|
||||
|
||||
func renderChart[T *clustermanagerchart.ChartConfig | *klusterletchart.ChartConfig](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)
|
||||
if err != nil {
|
||||
@@ -63,7 +81,18 @@ func RenderChart[T *clustermanagerchart.ChartConfig | *klusterletchart.ChartConf
|
||||
return nil, fmt.Errorf("error rendering cluster manager chart: %v", err)
|
||||
}
|
||||
|
||||
return rawObjects, nil
|
||||
// make sure the ns object is at the top of slice when createNamespace is true.
|
||||
rstObjects := [][]byte{}
|
||||
if createNamespace {
|
||||
nsObj, err := newNamespaceRawObject(namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rstObjects = [][]byte{nsObj}
|
||||
}
|
||||
rstObjects = append(rstObjects, rawObjects...)
|
||||
|
||||
return rstObjects, nil
|
||||
}
|
||||
|
||||
func getFiles(manifestFS embed.FS) ([]string, error) {
|
||||
@@ -172,3 +201,17 @@ func renderManifests(chart *chart.Chart, values chartutil.Values) ([][]byte, err
|
||||
}
|
||||
return rawObjects, nil
|
||||
}
|
||||
|
||||
func newNamespaceRawObject(namespace string) ([]byte, error) {
|
||||
ns := &corev1.Namespace{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "v1",
|
||||
Kind: "Namespace",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: namespace,
|
||||
},
|
||||
}
|
||||
|
||||
return yaml.Marshal(ns)
|
||||
}
|
||||
|
||||
@@ -84,6 +84,17 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
},
|
||||
expectedObjCnt: 7,
|
||||
},
|
||||
{
|
||||
name: "create namespace",
|
||||
namespace: "multicluster-engine",
|
||||
chartConfig: func() *clustermanagerchart.ChartConfig {
|
||||
config := NewDefaultClusterManagerChartConfig()
|
||||
config.CreateBootstrapToken = true
|
||||
config.CreateNamespace = true
|
||||
return config
|
||||
},
|
||||
expectedObjCnt: 10,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@@ -99,7 +110,7 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
version = config.Images.Tag
|
||||
}
|
||||
|
||||
objects, err := RenderChart(config, c.namespace, clustermanagerchart.ChartName, clustermanagerchart.ChartFiles)
|
||||
objects, err := RenderClusterManagerChart(config, c.namespace)
|
||||
if err != nil {
|
||||
t.Errorf("error rendering chart: %v", err)
|
||||
}
|
||||
@@ -115,6 +126,10 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
}
|
||||
outputObjs = append(outputObjs, obj)
|
||||
switch object := obj.(type) {
|
||||
case *corev1.Namespace:
|
||||
if object.Name != c.namespace {
|
||||
t.Errorf("expected namespace %s, got %s", c.namespace, object.Name)
|
||||
}
|
||||
case *appsv1.Deployment:
|
||||
if object.Namespace != c.namespace {
|
||||
t.Errorf("expected namespace is %s, but got %s", c.namespace, object.Namespace)
|
||||
@@ -135,7 +150,6 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
t.Errorf("failed to render images")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// output is for debug
|
||||
@@ -147,7 +161,6 @@ func TestClusterManagerConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestKlusterletConfig(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
namespace string
|
||||
@@ -213,6 +226,18 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
},
|
||||
expectedObjCnt: 2,
|
||||
},
|
||||
{
|
||||
name: "create namespace",
|
||||
namespace: "open-cluster-management",
|
||||
chartConfig: func() *klusterletchart.ChartConfig {
|
||||
config := NewDefaultKlusterletChartConfig()
|
||||
config.Klusterlet.ClusterName = "testCluster"
|
||||
config.Klusterlet.Mode = operatorv1.InstallModeSingleton
|
||||
config.CreateNamespace = true
|
||||
return config
|
||||
},
|
||||
expectedObjCnt: 7,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@@ -227,7 +252,7 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
version = config.Images.Tag
|
||||
}
|
||||
|
||||
objects, err := RenderChart(config, c.namespace, klusterletchart.ChartName, klusterletchart.ChartFiles)
|
||||
objects, err := RenderKlusterletChart(config, c.namespace)
|
||||
if err != nil {
|
||||
t.Errorf("error rendering chart: %v", err)
|
||||
}
|
||||
@@ -243,6 +268,10 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
}
|
||||
outputObjs = append(outputObjs, obj)
|
||||
switch object := obj.(type) {
|
||||
case *corev1.Namespace:
|
||||
if object.Name != c.namespace {
|
||||
t.Errorf("expected namespace %s, got %s", c.namespace, object.Name)
|
||||
}
|
||||
case *appsv1.Deployment:
|
||||
if object.Namespace != c.namespace {
|
||||
t.Errorf("expected namespace is %s, but got %s", c.namespace, object.Namespace)
|
||||
@@ -306,7 +335,6 @@ func TestKlusterletConfig(t *testing.T) {
|
||||
fmt.Sprintf("open-cluster-management-%s", object.Spec.ClusterName), object.Spec.Namespace)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user