@@ -11,12 +11,21 @@ import (
1111
1212 "github.com/hashicorp/terraform-plugin-framework/path"
1313 "github.com/hashicorp/terraform-plugin-framework/resource"
14+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
15+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
16+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
17+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
18+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
19+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
20+ "github.com/hashicorp/terraform-plugin-framework/types"
21+ "github.com/pluralsh/plural-cli/pkg/console"
1422 "github.com/samber/lo"
1523 "k8s.io/apimachinery/pkg/util/wait"
1624)
1725
1826var _ resource.Resource = & clusterResource {}
1927var _ resource.ResourceWithImportState = & clusterResource {}
28+ var _ resource.ResourceWithUpgradeState = & clusterResource {}
2029
2130func NewClusterResource () resource.Resource {
2231 return & clusterResource {}
@@ -68,21 +77,20 @@ func (r *clusterResource) Create(ctx context.Context, req resource.CreateRequest
6877 resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to create cluster, got error: %s" , err ))
6978 return
7079 }
80+ data .FromCreate (result , ctx , & resp .Diagnostics )
7181
7282 if r .kubeClient != nil || data .HasKubeconfig () {
73- if result .CreateCluster .DeployToken == nil {
74- resp .Diagnostics .AddError ("Client Error" , "Unable to fetch cluster deploy token" )
75- return
76- }
77-
78- if err = InstallOrUpgradeAgent (ctx , r .client , data .GetKubeconfig (), r .kubeClient , data .HelmRepoUrl .ValueString (),
79- data .HelmValues .ValueStringPointer (), r .consoleUrl , lo .FromPtr (result .CreateCluster .DeployToken ), result .CreateCluster .ID , & resp .Diagnostics ); err != nil {
80- resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to install operator, got error: %s" , err ))
81- return
83+ err = InstallOrUpgradeAgent (ctx , r .client , data .GetKubeconfig (), r .kubeClient , data .HelmRepoUrl .ValueString (),
84+ data .HelmValues .ValueStringPointer (), r .consoleUrl , lo .FromPtr (result .CreateCluster .DeployToken ),
85+ result .CreateCluster .ID , & resp .Diagnostics )
86+ if err != nil {
87+ resp .Diagnostics .AddWarning ("Agent Installation Failed" , fmt .Sprintf (
88+ "Unable to install agent, in order to retry run `terraform apply` again. Got error: %s" , err ))
89+ } else {
90+ data .AgentDeployed = types .BoolValue (true )
8291 }
8392 }
8493
85- data .FromCreate (result , ctx , & resp .Diagnostics )
8694 resp .Diagnostics .Append (resp .State .Set (ctx , & data )... )
8795}
8896
@@ -142,7 +150,7 @@ func (r *clusterResource) Update(ctx context.Context, req resource.UpdateRequest
142150 }
143151
144152 kubeconfigChanged := data .HasKubeconfig () && ! data .GetKubeconfig ().Unchanged (state .GetKubeconfig ())
145- reinstallable := ! data .HelmRepoUrl .Equal (state .HelmRepoUrl ) || kubeconfigChanged
153+ reinstallable := ! data .AgentDeployed . ValueBool () || ! data . HelmRepoUrl .Equal (state .HelmRepoUrl ) || kubeconfigChanged
146154 if reinstallable && (r .kubeClient != nil || data .HasKubeconfig ()) {
147155 clusterWithToken , err := r .client .GetClusterWithToken (ctx , data .Id .ValueStringPointer (), nil )
148156 if err != nil {
@@ -155,6 +163,8 @@ func (r *clusterResource) Update(ctx context.Context, req resource.UpdateRequest
155163 resp .Diagnostics .AddError ("Client Error" , fmt .Sprintf ("Unable to install operator, got error: %s" , err ))
156164 return
157165 }
166+
167+ data .AgentDeployed = types .BoolValue (true )
158168 }
159169
160170 resp .Diagnostics .Append (resp .State .Set (ctx , & data )... )
@@ -210,3 +220,140 @@ func (r *clusterResource) ImportState(ctx context.Context, req resource.ImportSt
210220
211221 resource .ImportStatePassthroughID (ctx , path .Root ("id" ), req , resp )
212222}
223+
224+ func (r * clusterResource ) UpgradeState (_ context.Context ) map [int64 ]resource.StateUpgrader {
225+ return map [int64 ]resource.StateUpgrader {
226+ // State upgrade from 0 to 1
227+ 0 : {
228+ PriorSchema : & schema.Schema {
229+ Version : 0 ,
230+ Attributes : map [string ]schema.Attribute {
231+ "id" : schema.StringAttribute {
232+ Computed : true ,
233+ PlanModifiers : []planmodifier.String {stringplanmodifier .UseStateForUnknown ()},
234+ },
235+ "inserted_at" : schema.StringAttribute {
236+ Computed : true ,
237+ PlanModifiers : []planmodifier.String {stringplanmodifier .UseStateForUnknown ()},
238+ },
239+ "name" : schema.StringAttribute {
240+ Required : true ,
241+ PlanModifiers : []planmodifier.String {stringplanmodifier .UseStateForUnknown ()},
242+ },
243+ "handle" : schema.StringAttribute {
244+ Optional : true ,
245+ Computed : true ,
246+ PlanModifiers : []planmodifier.String {stringplanmodifier .UseStateForUnknown ()},
247+ },
248+ "project_id" : schema.StringAttribute {
249+ Optional : true ,
250+ },
251+ "detach" : schema.BoolAttribute {
252+ Optional : true ,
253+ Computed : true ,
254+ Default : booldefault .StaticBool (false ),
255+ },
256+ "metadata" : schema.StringAttribute {
257+ Optional : true ,
258+ Computed : true ,
259+ Default : stringdefault .StaticString ("{}" ),
260+ PlanModifiers : []planmodifier.String {stringplanmodifier .UseStateForUnknown ()},
261+ },
262+ "helm_repo_url" : schema.StringAttribute {
263+ Optional : true ,
264+ Computed : true ,
265+ Default : stringdefault .StaticString (console .RepoUrl ),
266+ },
267+ "helm_values" : schema.StringAttribute {
268+ Optional : true ,
269+ },
270+ "kubeconfig" : common .KubeconfigResourceSchema (),
271+ "protect" : schema.BoolAttribute {
272+ Optional : true ,
273+ Computed : true ,
274+ Default : booldefault .StaticBool (false ),
275+ },
276+ "tags" : schema.MapAttribute {
277+ Optional : true ,
278+ ElementType : types .StringType ,
279+ },
280+ "bindings" : schema.SingleNestedAttribute {
281+ Optional : true ,
282+ Attributes : map [string ]schema.Attribute {
283+ "read" : schema.SetNestedAttribute {
284+ Optional : true ,
285+ NestedObject : schema.NestedAttributeObject {
286+ Attributes : map [string ]schema.Attribute {
287+ "group_id" : schema.StringAttribute {Optional : true },
288+ "id" : schema.StringAttribute {Optional : true },
289+ "user_id" : schema.StringAttribute {Optional : true },
290+ },
291+ },
292+ },
293+ "write" : schema.SetNestedAttribute {
294+ Optional : true ,
295+ Description : "Write policies of this cluster." ,
296+ MarkdownDescription : "Write policies of this cluster." ,
297+ NestedObject : schema.NestedAttributeObject {
298+ Attributes : map [string ]schema.Attribute {
299+ "group_id" : schema.StringAttribute {
300+ Optional : true ,
301+ },
302+ "id" : schema.StringAttribute {
303+ Optional : true ,
304+ },
305+ "user_id" : schema.StringAttribute {
306+ Optional : true ,
307+ },
308+ },
309+ },
310+ },
311+ },
312+ PlanModifiers : []planmodifier.Object {objectplanmodifier .UseStateForUnknown ()},
313+ },
314+ },
315+ },
316+ StateUpgrader : func (ctx context.Context , req resource.UpgradeStateRequest , resp * resource.UpgradeStateResponse ) {
317+ var priorStateData struct {
318+ Id types.String `tfsdk:"id"`
319+ InsertedAt types.String `tfsdk:"inserted_at"`
320+ Name types.String `tfsdk:"name"`
321+ Handle types.String `tfsdk:"handle"`
322+ ProjectId types.String `tfsdk:"project_id"`
323+ Detach types.Bool `tfsdk:"detach"`
324+ Protect types.Bool `tfsdk:"protect"`
325+ Tags types.Map `tfsdk:"tags"`
326+ Metadata types.String `tfsdk:"metadata"`
327+ Bindings * common.Bindings `tfsdk:"bindings"`
328+ HelmRepoUrl types.String `tfsdk:"helm_repo_url"`
329+ HelmValues types.String `tfsdk:"helm_values"`
330+ Kubeconfig * common.Kubeconfig `tfsdk:"kubeconfig"`
331+ }
332+
333+ resp .Diagnostics .Append (req .State .Get (ctx , & priorStateData )... )
334+ if resp .Diagnostics .HasError () {
335+ return
336+ }
337+
338+ upgradedStateData := cluster {
339+ Id : priorStateData .Id ,
340+ InsertedAt : priorStateData .InsertedAt ,
341+ Name : priorStateData .Name ,
342+ Handle : priorStateData .Handle ,
343+ ProjectId : priorStateData .ProjectId ,
344+ Detach : priorStateData .Detach ,
345+ Protect : priorStateData .Protect ,
346+ Tags : priorStateData .Tags ,
347+ Metadata : priorStateData .Metadata ,
348+ Bindings : priorStateData .Bindings ,
349+ HelmRepoUrl : priorStateData .HelmRepoUrl ,
350+ HelmValues : priorStateData .HelmValues ,
351+ Kubeconfig : priorStateData .Kubeconfig ,
352+ AgentDeployed : types .BoolValue (true ),
353+ }
354+
355+ resp .Diagnostics .Append (resp .State .Set (ctx , upgradedStateData )... )
356+ },
357+ },
358+ }
359+ }
0 commit comments