Skip to content
Draft
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: 1 addition & 1 deletion pkg/cmd/init/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ func (o *Options) deploySingletonControlplane(kubeClient kubernetes.Interface) e
o.Helm.SetValue("dryRun", "true")
}

o.Helm.InstallChart(releaseName, repoName, chartName)
o.Helm.InstallChart(releaseName, repoName, chartName, "")

// fetch the kubeconfig and get the token
if o.wait && !o.ClusteradmFlags.DryRun {
Expand Down
43 changes: 43 additions & 0 deletions pkg/cmd/install/hubaddon/addoncharts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright Contributors to the Open Cluster Management project
package hubaddon

type AddonChart struct {
ChartName string `json:"chartName"`
ReleaseName string `json:"releaseName"`
Namespace string `json:"namespace"`
Version string `json:"version"`
}

var AddonCharts = map[string][]AddonChart{
// ArgoCD Addons
"argocd": {{
ChartName: "argocd-pull-integration",
ReleaseName: "argocd-pull-integration",
Namespace: "argocd",
}},
"argocd-agent": {{
ChartName: "argocd-agent-addon",
ReleaseName: "argocd-agent-addon",
Namespace: "argocd",
}},
// Policy Framework Addons
"governance-policy-framework": {{
ChartName: "governance-policy-propagator",
ReleaseName: "governance-policy-propagator",
Namespace: "open-cluster-management",
}, {
ChartName: "governance-policy-addon-controller",
ReleaseName: "governance-policy-addon-controller",
Namespace: "open-cluster-management",
}},
}

func GetAddonNames() []string {
addonNames := make([]string, 0, len(AddonCharts))

for addon := range AddonCharts {
addonNames = append(addonNames, addon)
}

return addonNames
}
13 changes: 5 additions & 8 deletions pkg/cmd/install/hubaddon/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package hubaddon

import (
"fmt"
"strings"

genericclioptionsclusteradm "open-cluster-management.io/clusteradm/pkg/genericclioptions"
clusteradmhelpers "open-cluster-management.io/clusteradm/pkg/helpers"
Expand Down Expand Up @@ -48,14 +49,10 @@ func NewCmd(clusteradmFlags *genericclioptionsclusteradm.ClusteradmFlags, stream
},
}

cmd.Flags().StringVar(&o.names, "names", "", "Names of the built-in add-on to install (comma separated). The built-in add-ons are: argocd, argocd-agent, governance-policy-framework")
cmd.Flags().StringVar(&o.values.Namespace, "namespace", "open-cluster-management", "Namespace of the built-in add-on to install. Defaults to open-cluster-management")
cmd.Flags().BoolVar(&o.values.CreateNamespace, "create-namespace", false, "If true, automatically create the specified namespace")
cmd.Flags().StringVar(&o.outputFile, "output-file", "", "The generated resources will be copied in the specified file")
cmd.Flags().StringVar(&o.bundleVersion, "bundle-version", "default",
"The image version tag to use when deploying the hub add-on(s) (e.g. v0.6.0). Defaults to the latest released version. You can also set \"latest\" to install the latest development version.")
cmd.Flags().StringVar(&o.versionBundleFile, "bundle-version-overrides", "",
"Path to a file containing version bundle overrides. Optional. If provided, overrides component versions within the selected version bundle.")
cmd.Flags().StringVar(&o.names, "names", "", "Names of the add-ons to install (comma separated) from the "+ChartRepoURL+" repository. The built-in add-ons are: "+strings.Join(GetAddonNames(), ", "))
cmd.Flags().StringVar(&o.namespace, "namespace", "", "Namespace in which to install the add-ons. If not provided, the add-ons will be installed according to their chart.")
cmd.Flags().BoolVar(&o.createNamespace, "create-namespace", false, "If true, automatically create the specified namespace.")
cmd.Flags().StringVar(&o.chartVersion, "chart-version", "", "The chart version to use when deploying the hub add-on(s) (e.g. 0.6.0). Defaults to an empty string, which will fetch the latest released version.")

return cmd
}
178 changes: 37 additions & 141 deletions pkg/cmd/install/hubaddon/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,23 @@
package hubaddon

import (
"context"
"fmt"
"os"
"strings"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"open-cluster-management.io/clusteradm/pkg/helpers/reader"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"

"github.com/spf13/cobra"
"k8s.io/klog/v2"

"open-cluster-management.io/clusteradm/pkg/cmd/install/hubaddon/scenario"
"open-cluster-management.io/clusteradm/pkg/version"
)

var (
url = "https://open-cluster-management.io/helm-charts"
repoName = "ocm"
argocdAddonName = "argocd"
argocdNamespace = "argocd"
argocdReleaseName = "argocd-pull-integration"
argocdChartName = "argocd-pull-integration"
argocdAgentAddonName = "argocd-agent"
argocdAgentReleaseName = "argocd-agent-addon"
argocdAgentChartName = "argocd-agent-addon"
policyFrameworkAddonName = "governance-policy-framework"
const (
ChartRepoURL = "https://open-cluster-management.io/helm-charts"
chartRepoName = "ocm"
)

func (o *Options) complete(_ *cobra.Command, _ []string) (err error) {
klog.V(1).InfoS("addon options:", "dry-run", o.ClusteradmFlags.DryRun, "names", o.names, "output-file", o.outputFile)
klog.V(1).InfoS("addon options:", "dry-run", o.ClusteradmFlags.DryRun, "names", o.names)
return nil
}

Expand All @@ -48,155 +32,67 @@ func (o *Options) validate() (err error) {
return fmt.Errorf("names is missing")
}

names := strings.Split(o.names, ",")
for _, n := range names {
if n != argocdAddonName && n != argocdAgentAddonName && n != policyFrameworkAddonName {
return fmt.Errorf("invalid add-on name %s", n)
}
}

versionBundle, err := version.GetVersionBundle(o.bundleVersion, o.versionBundleFile)
if err != nil {
return err
}

o.values.BundleVersion = versionBundle

return nil
}

func (o *Options) run() error {
alreadyProvidedAddons := make(map[string]bool)
addons := make([]string, 0)
names := strings.Split(o.names, ",")
for _, n := range names {
if _, ok := alreadyProvidedAddons[n]; !ok {
alreadyProvidedAddons[n] = true
addons = append(addons, strings.TrimSpace(n))
}
addonsToInstall := sets.New[string]()
names := strings.SplitSeq(o.names, ",")
for n := range names {
addonsToInstall.Insert(n)
}

var filteredAddons []string
for _, a := range addons {
if a == argocdAddonName || a == argocdAgentAddonName {
if err := o.runWithHelmClient(a); err != nil {
return err
}
} else {
filteredAddons = append(filteredAddons, a)
}
}
addons = filteredAddons
if len(addons) == 0 {
return nil
}

o.values.HubAddons = addons

klog.V(3).InfoS("values:", "addon", o.values.HubAddons)

if o.values.CreateNamespace {
if err := o.createNamespace(); err != nil {
return err
var errs []error
for addon := range addonsToInstall {
if err := o.runWithHelmClient(addon); err != nil {
errs = append(errs, err)
}
}

return o.runWithClient()
return utilerrors.NewAggregate(errs)
}

func (o *Options) runWithClient() error {

r := reader.NewResourceReader(o.ClusteradmFlags.KubectlFactory, o.ClusteradmFlags.DryRun, o.Streams)

for _, addon := range o.values.HubAddons {
files, ok := scenario.AddonDeploymentFiles[addon]
if !ok {
continue
}
err := r.Apply(scenario.Files, o.values, files.CRDFiles...)
if err != nil {
return fmt.Errorf("error deploying %s CRDs: %w", addon, err)
}
err = r.Apply(scenario.Files, o.values, files.ConfigFiles...)
if err != nil {
return fmt.Errorf("error deploying %s dependencies: %w", addon, err)
}
err = r.Apply(scenario.Files, o.values, files.DeploymentFiles...)
if err != nil {
return fmt.Errorf("error deploying %s deployments: %w", addon, err)
}

fmt.Fprintf(o.Streams.Out, "Installing built-in %s add-on to the Hub cluster...\n", addon)
func GetAddonCharts(addon string, namespace string, chartVersion string) []AddonChart {
addonChart, ok := AddonCharts[addon]
if !ok {
addonChart = []AddonChart{{
ChartName: addon,
ReleaseName: addon,
}}
}

if len(o.outputFile) > 0 {
sh, err := os.OpenFile(o.outputFile, os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
return err
}
_, err = fmt.Fprintf(sh, "%s", string(r.RawAppliedResources()))
if err != nil {
return err
}
if err := sh.Close(); err != nil {
return err
for _, addonChart := range addonChart {
if addonChart.Namespace == "" {
addonChart.Namespace = namespace
}
}

return nil
}

func (o *Options) createNamespace() error {
clientSet, err := o.ClusteradmFlags.KubectlFactory.KubernetesClientSet()
if err != nil {
return fmt.Errorf("failed to create kubernetes clientSet")
}

ns, err := clientSet.CoreV1().Namespaces().Get(context.Background(), o.values.Namespace, metav1.GetOptions{})
if err != nil && errors.IsNotFound(err) {
ns, err = clientSet.CoreV1().Namespaces().Create(context.Background(), &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: o.values.Namespace,
},
}, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("failed to create namespace %s: %w", ns, err)
if addonChart.Version == "" {
addonChart.Version = chartVersion
}
} else if err != nil {
return fmt.Errorf("failed to get namespace %s: %w", ns, err)
}

return nil
return addonChart
}

func (o *Options) runWithHelmClient(addon string) error {
if addon == argocdAddonName {
o.Helm.WithNamespace(argocdNamespace)
o.Helm.WithCreateNamespace(o.values.CreateNamespace)
if err := o.Helm.PrepareChart(repoName, url); err != nil {
return err
}
var errs []error

if o.ClusteradmFlags.DryRun {
o.Helm.SetValue("dryRun", "true")
}
for _, addonChart := range GetAddonCharts(addon, o.namespace, o.chartVersion) {
o.Helm.WithNamespace(addonChart.Namespace)
o.Helm.WithCreateNamespace(o.createNamespace)

o.Helm.InstallChart(argocdReleaseName, repoName, argocdChartName)
}
if err := o.Helm.PrepareChart(chartRepoName, ChartRepoURL); err != nil {
errs = append(errs, err)

if addon == argocdAgentAddonName {
o.Helm.WithNamespace(argocdNamespace)
o.Helm.WithCreateNamespace(o.values.CreateNamespace)
if err := o.Helm.PrepareChart(repoName, url); err != nil {
return err
continue
}

if o.ClusteradmFlags.DryRun {
o.Helm.SetValue("dryRun", "true")
}

o.Helm.InstallChart(argocdAgentReleaseName, repoName, argocdAgentChartName)
o.Helm.InstallChart(addonChart.ReleaseName, chartRepoName, addonChart.ChartName, addonChart.Version)
}

return nil
return utilerrors.NewAggregate(errs)
}
Loading