11package spectrocloud
22
33import (
4+ "log"
45 "strings"
56
67 "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -12,6 +13,204 @@ import (
1213 "github.com/spectrocloud/terraform-provider-spectrocloud/types"
1314)
1415
16+ // readAddonDeploymentMultiple reads multiple addon profiles from the cluster
17+ func readAddonDeploymentMultiple (c * client.V1Client , d * schema.ResourceData , cluster * models.V1SpectroCluster ) (diag.Diagnostics , bool ) {
18+ var diags diag.Diagnostics
19+
20+ // Get the profile UIDs from resource ID
21+ profileUIDs , err := getClusterProfileUIDs (d .Id ())
22+ if err != nil {
23+ // Fallback to legacy single profile handling
24+ return readAddonDeployment (c , d , cluster )
25+ }
26+
27+ // Build a map of profile UIDs we're tracking
28+ trackedProfiles := make (map [string ]bool )
29+ for _ , uid := range profileUIDs {
30+ trackedProfiles [uid ] = true
31+ }
32+
33+ // Get existing profiles from config to preserve pack configurations
34+ existingProfiles := d .Get ("cluster_profile" ).([]interface {})
35+ existingProfilesMap := make (map [string ]map [string ]interface {})
36+ for _ , p := range existingProfiles {
37+ if p == nil {
38+ continue
39+ }
40+ profile := p .(map [string ]interface {})
41+ if id , ok := profile ["id" ].(string ); ok && id != "" {
42+ existingProfilesMap [id ] = profile
43+ }
44+ }
45+
46+ // Flatten all tracked profiles from cluster state
47+ clusterProfiles := make ([]interface {}, 0 )
48+ foundProfiles := make ([]string , 0 )
49+
50+ for _ , template := range cluster .Spec .ClusterProfileTemplates {
51+ if template == nil {
52+ continue
53+ }
54+
55+ // Check if this profile is one we're tracking
56+ if ! trackedProfiles [template .UID ] {
57+ // Check by fetching the profile and matching by name (for version upgrades)
58+ found := false
59+ for trackedUID := range trackedProfiles {
60+ trackedProfile , err := c .GetClusterProfile (trackedUID )
61+ if err != nil {
62+ continue
63+ }
64+ if trackedProfile != nil && trackedProfile .Metadata != nil &&
65+ template .Name == trackedProfile .Metadata .Name {
66+ found = true
67+ break
68+ }
69+ }
70+ if ! found {
71+ continue
72+ }
73+ }
74+
75+ // Flatten this profile
76+ profileData , err := flattenAddonDeploymentProfile (c , d , template , existingProfilesMap )
77+ if err != nil {
78+ log .Printf ("Warning: failed to flatten profile %s: %v" , template .UID , err )
79+ continue
80+ }
81+
82+ clusterProfiles = append (clusterProfiles , profileData )
83+ foundProfiles = append (foundProfiles , template .UID )
84+ }
85+
86+ // If no profiles found, mark resource as deleted
87+ if len (clusterProfiles ) == 0 {
88+ d .SetId ("" )
89+ return diags , false
90+ }
91+
92+ // Update cluster_profile in state
93+ if err := d .Set ("cluster_profile" , clusterProfiles ); err != nil {
94+ return diag .FromErr (err ), false
95+ }
96+
97+ // Update resource ID with current profile UIDs
98+ clusterUid := d .Get ("cluster_uid" ).(string )
99+ d .SetId (buildAddonDeploymentId (clusterUid , foundProfiles ))
100+
101+ return diags , true
102+ }
103+
104+ // flattenAddonDeploymentProfile flattens a single profile template
105+ func flattenAddonDeploymentProfile (c * client.V1Client , d * schema.ResourceData , profile * models.V1ClusterProfileTemplate , existingProfilesMap map [string ]map [string ]interface {}) (map [string ]interface {}, error ) {
106+ clusterProfile := make (map [string ]interface {})
107+ clusterProfile ["id" ] = profile .UID
108+
109+ // Check if user has defined packs in their config for this profile
110+ hasPacksInConfig := false
111+ if existingConfig , exists := existingProfilesMap [profile .UID ]; exists {
112+ if packs , ok := existingConfig ["pack" ]; ok && packs != nil {
113+ packsList := packs .([]interface {})
114+ if len (packsList ) > 0 {
115+ hasPacksInConfig = true
116+ }
117+ }
118+ }
119+
120+ // Only flatten packs if user has defined them in config
121+ if hasPacksInConfig {
122+ packManifests , diagResult , done := getPacksContent (profile .Packs , c , d )
123+ if done {
124+ log .Printf ("Warning: error getting pack content for profile %s: %v" , profile .UID , diagResult )
125+ } else {
126+ diagPacks := make ([]* models.V1PackManifestEntity , 0 )
127+ if existingConfig , exists := existingProfilesMap [profile .UID ]; exists {
128+ if packsRaw , ok := existingConfig ["pack" ]; ok && packsRaw != nil {
129+ for _ , pack := range packsRaw .([]interface {}) {
130+ if p , e := toAddonDeploymentPackCreate (pack ); e == nil {
131+ diagPacks = append (diagPacks , p )
132+ }
133+ }
134+ }
135+ }
136+
137+ // Build registry maps for this profile
138+ registryNameMap := buildPackRegistryNameMapForProfile (existingProfilesMap [profile .UID ])
139+ registryUIDMap := buildPackRegistryUIDMapForProfile (existingProfilesMap [profile .UID ])
140+
141+ packs , err := flattenPacksWithRegistryMaps (c , diagPacks , profile .Packs , packManifests , registryNameMap , registryUIDMap )
142+ if err == nil {
143+ clusterProfile ["pack" ] = packs
144+ }
145+ }
146+ }
147+
148+ // Flatten profile variables
149+ clusterUID := d .Get ("cluster_uid" ).(string )
150+ if clusterUID != "" {
151+ clusterVars , err := c .GetClusterVariables (clusterUID )
152+ if err == nil {
153+ for _ , clusterVar := range clusterVars {
154+ if clusterVar .ProfileUID != nil && * clusterVar .ProfileUID == profile .UID && clusterVar .Variables != nil {
155+ vars := make (map [string ]interface {})
156+ for _ , v := range clusterVar .Variables {
157+ if v .Name != nil && v .Value != "" {
158+ vars [* v .Name ] = v .Value
159+ }
160+ }
161+ if len (vars ) > 0 {
162+ clusterProfile ["variables" ] = vars
163+ }
164+ break
165+ }
166+ }
167+ }
168+ }
169+
170+ return clusterProfile , nil
171+ }
172+
173+ // buildPackRegistryNameMapForProfile builds a registry name map for a single profile
174+ // Returns a map indicating which packs have registry_name set
175+ func buildPackRegistryNameMapForProfile (profileConfig map [string ]interface {}) map [string ]bool {
176+ registryNameMap := make (map [string ]bool )
177+ if profileConfig == nil {
178+ return registryNameMap
179+ }
180+
181+ if packsRaw , ok := profileConfig ["pack" ]; ok && packsRaw != nil {
182+ for _ , pack := range packsRaw .([]interface {}) {
183+ p := pack .(map [string ]interface {})
184+ packName := p ["name" ].(string )
185+ if regName , ok := p ["registry_name" ]; ok && regName != nil && regName .(string ) != "" {
186+ registryNameMap [packName ] = true
187+ }
188+ }
189+ }
190+ return registryNameMap
191+ }
192+
193+ // buildPackRegistryUIDMapForProfile builds a registry UID map for a single profile
194+ // Returns a map indicating which packs have registry_uid set
195+ func buildPackRegistryUIDMapForProfile (profileConfig map [string ]interface {}) map [string ]bool {
196+ registryUIDMap := make (map [string ]bool )
197+ if profileConfig == nil {
198+ return registryUIDMap
199+ }
200+
201+ if packsRaw , ok := profileConfig ["pack" ]; ok && packsRaw != nil {
202+ for _ , pack := range packsRaw .([]interface {}) {
203+ p := pack .(map [string ]interface {})
204+ packName := p ["name" ].(string )
205+ if regUID , ok := p ["registry_uid" ]; ok && regUID != nil && regUID .(string ) != "" {
206+ registryUIDMap [packName ] = true
207+ }
208+ }
209+ }
210+ return registryUIDMap
211+ }
212+
213+ // readAddonDeployment is the legacy function for reading a single addon profile (kept for backward compatibility)
15214func readAddonDeployment (c * client.V1Client , d * schema.ResourceData , cluster * models.V1SpectroCluster ) (diag.Diagnostics , bool ) {
16215
17216 var diags diag.Diagnostics
0 commit comments