@@ -10,6 +10,9 @@ import (
1010 "helm.sh/helm/v3/pkg/chart"
1111 "helm.sh/helm/v3/pkg/chartutil"
1212 "helm.sh/helm/v3/pkg/engine"
13+ "helm.sh/helm/v3/pkg/releaseutil"
14+ "k8s.io/apimachinery/pkg/api/meta"
15+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1316 "k8s.io/apimachinery/pkg/runtime"
1417 "k8s.io/apimachinery/pkg/runtime/serializer"
1518 "k8s.io/apimachinery/pkg/util/yaml"
@@ -42,28 +45,59 @@ type helmDefaultValues struct {
4245}
4346
4447type HelmAgentAddon struct {
45- decoder runtime.Decoder
46- chart * chart.Chart
47- getValuesFuncs []GetValuesFunc
48- agentAddonOptions agent.AgentAddonOptions
49- trimCRDDescription bool
50- hostingCluster * clusterv1.ManagedCluster
51- agentInstallNamespace func (addon * addonapiv1alpha1.ManagedClusterAddOn ) string
48+ decoder runtime.Decoder
49+ chart * chart.Chart
50+ getValuesFuncs []GetValuesFunc
51+ agentAddonOptions agent.AgentAddonOptions
52+ trimCRDDescription bool
53+ hostingCluster * clusterv1.ManagedCluster
54+ agentInstallNamespace func (addon * addonapiv1alpha1.ManagedClusterAddOn ) string
55+ createAgentInstallNamespace bool
56+ helmEngineStrict bool
5257}
5358
5459func newHelmAgentAddon (factory * AgentAddonFactory , chart * chart.Chart ) * HelmAgentAddon {
5560 return & HelmAgentAddon {
56- decoder : serializer .NewCodecFactory (factory .scheme ).UniversalDeserializer (),
57- chart : chart ,
58- getValuesFuncs : factory .getValuesFuncs ,
59- agentAddonOptions : factory .agentAddonOptions ,
60- trimCRDDescription : factory .trimCRDDescription ,
61- hostingCluster : factory .hostingCluster ,
62- agentInstallNamespace : factory .agentInstallNamespace ,
61+ decoder : serializer .NewCodecFactory (factory .scheme ).UniversalDeserializer (),
62+ chart : chart ,
63+ getValuesFuncs : factory .getValuesFuncs ,
64+ agentAddonOptions : factory .agentAddonOptions ,
65+ trimCRDDescription : factory .trimCRDDescription ,
66+ hostingCluster : factory .hostingCluster ,
67+ agentInstallNamespace : factory .agentInstallNamespace ,
68+ createAgentInstallNamespace : factory .createAgentInstallNamespace ,
69+ helmEngineStrict : factory .helmEngineStrict ,
6370 }
6471}
6572
6673func (a * HelmAgentAddon ) Manifests (
74+ cluster * clusterv1.ManagedCluster ,
75+ addon * addonapiv1alpha1.ManagedClusterAddOn ) ([]runtime.Object , error ) {
76+ objects , err := a .renderManifests (cluster , addon )
77+ if err != nil {
78+ return nil , err
79+ }
80+
81+ manifests := make ([]Manifest , 0 , len (objects ))
82+ for _ , obj := range objects {
83+ a , err := meta .TypeAccessor (obj )
84+ if err != nil {
85+ return nil , err
86+ }
87+ manifests = append (manifests , Manifest {
88+ Object : obj ,
89+ Kind : a .GetKind (),
90+ })
91+ }
92+ sortManifestsByKind (manifests , releaseutil .InstallOrder )
93+
94+ for i , manifest := range manifests {
95+ objects [i ] = manifest .Object
96+ }
97+ return objects , nil
98+ }
99+
100+ func (a * HelmAgentAddon ) renderManifests (
67101 cluster * clusterv1.ManagedCluster ,
68102 addon * addonapiv1alpha1.ManagedClusterAddOn ) ([]runtime.Object , error ) {
69103 var objects []runtime.Object
@@ -74,7 +108,7 @@ func (a *HelmAgentAddon) Manifests(
74108 }
75109
76110 helmEngine := engine.Engine {
77- Strict : true ,
111+ Strict : a . helmEngineStrict ,
78112 LintMode : false ,
79113 }
80114
@@ -93,16 +127,8 @@ func (a *HelmAgentAddon) Manifests(
93127 return objects , err
94128 }
95129
96- // sort the filenames of the templates so the manifests are ordered consistently
97- keys := make ([]string , 0 , len (templates ))
98- for k := range templates {
99- keys = append (keys , k )
100- }
101- sort .Strings (keys )
102-
103- for _ , k := range keys {
104- data := templates [k ]
105-
130+ agentInstallNamespace := a .getValueAgentInstallNamespace (addon )
131+ for k , data := range templates {
106132 if len (data ) == 0 {
107133 continue
108134 }
@@ -132,6 +158,13 @@ func (a *HelmAgentAddon) Manifests(
132158 }
133159 }
134160
161+ if agentInstallNamespace != "" && a .createAgentInstallNamespace {
162+ var ns unstructured.Unstructured
163+ ns .SetAPIVersion ("v1" )
164+ ns .SetKind ("Namespace" )
165+ ns .SetName (agentInstallNamespace )
166+ objects = append (objects , & ns )
167+ }
135168 }
136169
137170 if a .trimCRDDescription {
@@ -260,3 +293,47 @@ func (a *HelmAgentAddon) releaseOptions(
260293 Namespace : a .getValueAgentInstallNamespace (addon ),
261294 }
262295}
296+
297+ // Manifest represents a manifest file, which has a name and some content.
298+ type Manifest struct {
299+ Object runtime.Object
300+ Kind string
301+ }
302+
303+ // sort manifests by kind.
304+ //
305+ // Results are sorted by 'ordering', keeping order of items with equal kind/priority
306+ func sortManifestsByKind (manifests []Manifest , ordering releaseutil.KindSortOrder ) []Manifest {
307+ sort .SliceStable (manifests , func (i , j int ) bool {
308+ return lessByKind (manifests [i ], manifests [j ], manifests [i ].Kind , manifests [j ].Kind , ordering )
309+ })
310+
311+ return manifests
312+ }
313+
314+ func lessByKind (a interface {}, b interface {}, kindA string , kindB string , o releaseutil.KindSortOrder ) bool {
315+ ordering := make (map [string ]int , len (o ))
316+ for v , k := range o {
317+ ordering [k ] = v
318+ }
319+
320+ first , aok := ordering [kindA ]
321+ second , bok := ordering [kindB ]
322+
323+ if ! aok && ! bok {
324+ // if both are unknown then sort alphabetically by kind, keep original order if same kind
325+ if kindA != kindB {
326+ return kindA < kindB
327+ }
328+ return first < second
329+ }
330+ // unknown kind is last
331+ if ! aok {
332+ return false
333+ }
334+ if ! bok {
335+ return true
336+ }
337+ // sort different kinds, keep original order if same priority
338+ return first < second
339+ }
0 commit comments