Skip to content

Commit 1297e05

Browse files
committed
Merge branch 'main' of github.com:pluralsh/terraform-provider-plural
2 parents 63aea6f + 143a0d4 commit 1297e05

File tree

7 files changed

+163
-45
lines changed

7 files changed

+163
-45
lines changed

docs/resources/provider.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,14 @@ A representation of a provider you can deploy your clusters to.
2020
- `cloud` (String) The name of the cloud service for this provider.
2121
- `cloud_settings` (Attributes) Cloud-specific settings for a provider. (see [below for nested schema](#nestedatt--cloud_settings))
2222
- `name` (String) Human-readable name of this provider. Globally unique.
23+
24+
### Optional
25+
2326
- `namespace` (String) The namespace the Cluster API resources are deployed into.
2427

2528
### Read-Only
2629

30+
- `editable` (Boolean) Whether this provider is editable.
2731
- `id` (String) Internal identifier of this provider.
2832

2933
<a id="nestedatt--cloud_settings"></a>

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ require (
99
github.com/hashicorp/terraform-plugin-framework-validators v0.12.0
1010
github.com/hashicorp/terraform-plugin-log v0.9.0
1111
github.com/mitchellh/go-homedir v1.1.0
12-
github.com/pluralsh/console-client-go v0.0.39
12+
github.com/pluralsh/console-client-go v0.0.42
1313
github.com/pluralsh/plural-cli v0.8.1-0.20231114161007-183eafb99b03
1414
github.com/pluralsh/polly v0.1.4
1515
github.com/samber/lo v1.38.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
856856
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
857857
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
858858
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
859-
github.com/pluralsh/console-client-go v0.0.39 h1:Edj6iUZjAheeGP7x12dSgQFNQeBmHhgZQTB6FplH/Ys=
860-
github.com/pluralsh/console-client-go v0.0.39/go.mod h1:kZjk0pXAWnvyj+miXveCho4kKQaX1Tm3CGAM+iwurWU=
859+
github.com/pluralsh/console-client-go v0.0.42 h1:9qeYWVNePx0RrHLUB83gGKRMPvSCMd81/PVPNWQYti8=
860+
github.com/pluralsh/console-client-go v0.0.42/go.mod h1:u/RjzXE3wtl3L6wiWxwhQHSpxFX46+EYvpkss2mALN4=
861861
github.com/pluralsh/gqlclient v1.11.0 h1:FfXW7FiEJLHOfTAa7NxDb8jb3aMZNIpCAcG+bg8uHYA=
862862
github.com/pluralsh/gqlclient v1.11.0/go.mod h1:qSXKUlio1F2DRPy8el4oFYsmpKbkUYspgPB87T4it5I=
863863
github.com/pluralsh/plural-cli v0.8.1-0.20231114161007-183eafb99b03 h1:toUJzv4+4SYGsw8kvrx2oQxrmKu8XYirrNmNyxx9NHk=

internal/model/cluster.go

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
package model
22

3-
import "github.com/hashicorp/terraform-plugin-framework/types"
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-framework/attr"
7+
"github.com/hashicorp/terraform-plugin-framework/types"
8+
console "github.com/pluralsh/console-client-go"
9+
)
410

511
// Cluster describes the cluster resource and data source model.
612
type Cluster struct {
713
Id types.String `tfsdk:"id"`
814
InseredAt types.String `tfsdk:"inserted_at"`
915
Name types.String `tfsdk:"name"`
1016
Handle types.String `tfsdk:"handle"`
17+
Version types.String `tfsdk:"version"`
18+
ProviderId types.String `tfsdk:"provider_id"`
1119
Cloud types.String `tfsdk:"cloud"`
1220
CloudSettings ClusterCloudSettings `tfsdk:"cloud_settings"`
1321
Protect types.Bool `tfsdk:"protect"`
@@ -66,3 +74,98 @@ type KubeconfigExec struct {
6674
Env types.String `tfsdk:"env"`
6775
APIVersion types.String `tfsdk:"api_version"`
6876
}
77+
78+
func (c *Cluster) CloudSettingsAttributes() *console.CloudSettingsAttributes {
79+
if IsCloud(c.Cloud.ValueString(), CloudAWS) {
80+
return &console.CloudSettingsAttributes{
81+
Aws: &console.AwsCloudAttributes{
82+
Region: c.CloudSettings.AWS.Region.ValueStringPointer(),
83+
},
84+
}
85+
}
86+
87+
if IsCloud(c.Cloud.ValueString(), CloudAzure) {
88+
return &console.CloudSettingsAttributes{
89+
Azure: &console.AzureCloudAttributes{
90+
Location: c.CloudSettings.Azure.Location.ValueStringPointer(),
91+
SubscriptionID: c.CloudSettings.Azure.SubscriptionId.ValueStringPointer(),
92+
ResourceGroup: c.CloudSettings.Azure.ResourceGroup.ValueStringPointer(),
93+
Network: c.CloudSettings.Azure.Network.ValueStringPointer(),
94+
},
95+
}
96+
}
97+
98+
if IsCloud(c.Cloud.ValueString(), CloudGCP) {
99+
return &console.CloudSettingsAttributes{
100+
Gcp: &console.GcpCloudAttributes{
101+
Project: c.CloudSettings.GCP.Project.ValueStringPointer(),
102+
Network: c.CloudSettings.GCP.Network.ValueStringPointer(),
103+
Region: c.CloudSettings.GCP.Region.ValueStringPointer(),
104+
},
105+
}
106+
}
107+
108+
return nil
109+
}
110+
111+
func (c *Cluster) TagsAttribute() (result []*console.TagAttributes) {
112+
elements := make(map[string]types.String, len(c.Tags.Elements()))
113+
_ = c.Tags.ElementsAs(context.TODO(), &elements, false) // TODO: Context and skipped diagnostics.
114+
for k, v := range elements {
115+
result = append(result, &console.TagAttributes{Name: k, Value: v.ValueString()})
116+
}
117+
118+
return
119+
}
120+
121+
func (c *Cluster) CreateAttributes() console.ClusterAttributes {
122+
return console.ClusterAttributes{
123+
Name: c.Name.ValueString(),
124+
Handle: c.Handle.ValueStringPointer(),
125+
Version: c.Version.ValueStringPointer(),
126+
ProviderID: c.ProviderId.ValueStringPointer(),
127+
CloudSettings: c.CloudSettingsAttributes(),
128+
Tags: c.TagsAttribute(),
129+
Protect: c.Protect.ValueBoolPointer(),
130+
}
131+
}
132+
133+
func (c *Cluster) UpdateAttributes() console.ClusterUpdateAttributes {
134+
return console.ClusterUpdateAttributes{
135+
Handle: c.Handle.ValueStringPointer(),
136+
Version: c.Version.ValueStringPointer(),
137+
Protect: c.Protect.ValueBoolPointer(),
138+
}
139+
}
140+
141+
func (c *Cluster) TagsFrom(tags []*console.ClusterTags) {
142+
elements := map[string]attr.Value{}
143+
for _, v := range tags {
144+
elements[v.Name] = types.StringValue(v.Value)
145+
}
146+
147+
tagsValue, _ := types.MapValue(types.StringType, elements) // TODO: Skipped diagnostics.
148+
c.Tags = tagsValue
149+
}
150+
151+
func (c *Cluster) From(cl *console.ClusterFragment) {
152+
c.Id = types.StringValue(cl.ID)
153+
c.InseredAt = types.StringPointerValue(cl.InsertedAt)
154+
c.Name = types.StringValue(cl.Name)
155+
c.Handle = types.StringPointerValue(cl.Handle)
156+
c.Version = types.StringPointerValue(cl.Version)
157+
c.ProviderId = types.StringValue(cl.Provider.ID)
158+
c.Protect = types.BoolPointerValue(cl.Protect)
159+
c.TagsFrom(cl.Tags)
160+
}
161+
162+
func (c *Cluster) FromCreate(cc *console.CreateCluster) {
163+
c.Id = types.StringValue(cc.CreateCluster.ID)
164+
c.InseredAt = types.StringPointerValue(cc.CreateCluster.InsertedAt)
165+
c.Name = types.StringValue(cc.CreateCluster.Name)
166+
c.Handle = types.StringPointerValue(cc.CreateCluster.Handle)
167+
c.Version = types.StringPointerValue(cc.CreateCluster.Version)
168+
c.ProviderId = types.StringValue(cc.CreateCluster.Provider.ID)
169+
c.Protect = types.BoolPointerValue(cc.CreateCluster.Protect)
170+
c.TagsFrom(cc.CreateCluster.Tags)
171+
}

internal/model/provider.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,16 @@ import (
99
type Provider struct {
1010
Id types.String `tfsdk:"id"`
1111
Name types.String `tfsdk:"name"`
12-
Namespace types.String `tfsdk:"name"`
12+
Namespace types.String `tfsdk:"namespace"`
13+
Editable types.Bool `tfsdk:"editable"`
1314
Cloud types.String `tfsdk:"cloud"`
1415
CloudSettings ProviderCloudSettings `tfsdk:"cloud_settings"`
1516
}
1617

1718
type ProviderCloudSettings struct {
18-
AWS ProviderCloudSettingsAWS `tfsdk:"aws"`
19-
Azure ProviderCloudSettingsAzure `tfsdk:"azure"`
20-
GCP ProviderCloudSettingsGCP `tfsdk:"gcp"`
19+
AWS *ProviderCloudSettingsAWS `tfsdk:"aws"`
20+
Azure *ProviderCloudSettingsAzure `tfsdk:"azure"`
21+
GCP *ProviderCloudSettingsGCP `tfsdk:"gcp"`
2122
}
2223

2324
type ProviderCloudSettingsAWS struct {
@@ -68,7 +69,7 @@ func (p *Provider) CloudProviderSettingsAttributes() *console.CloudProviderSetti
6869
return nil
6970
}
7071

71-
func (p *Provider) Attributes() console.ClusterProviderAttributes {
72+
func (p *Provider) CreateAttributes() console.ClusterProviderAttributes {
7273
return console.ClusterProviderAttributes{
7374
Name: p.Name.ValueString(),
7475
Namespace: p.Namespace.ValueStringPointer(),
@@ -87,5 +88,6 @@ func (p *Provider) From(cp *console.ClusterProviderFragment) {
8788
p.Id = types.StringValue(cp.ID)
8889
p.Name = types.StringValue(cp.Name)
8990
p.Namespace = types.StringValue(cp.Namespace)
91+
p.Editable = types.BoolPointerValue(cp.Editable)
9092
p.Cloud = types.StringValue(cp.Cloud)
9193
}

internal/resource/cluster/cluster.go

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1818
"github.com/hashicorp/terraform-plugin-framework/types"
1919
"github.com/hashicorp/terraform-plugin-log/tflog"
20-
console "github.com/pluralsh/console-client-go"
2120
)
2221

2322
var _ resource.Resource = &clusterResource{}
@@ -62,6 +61,15 @@ func (r *clusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
6261
Optional: true,
6362
Computed: true,
6463
},
64+
"version": schema.StringAttribute{
65+
MarkdownDescription: "",
66+
Optional: true,
67+
Computed: true,
68+
},
69+
"provider_id": schema.StringAttribute{
70+
MarkdownDescription: "",
71+
Required: true,
72+
},
6573
"cloud": schema.StringAttribute{
6674
MarkdownDescription: "The cloud provider used to create this cluster.",
6775
Required: true,
@@ -118,26 +126,14 @@ func (r *clusterResource) Create(ctx context.Context, req resource.CreateRequest
118126
return
119127
}
120128

121-
attrs := console.ClusterAttributes{
122-
Name: data.Name.ValueString(),
123-
Handle: data.Handle.ValueStringPointer(),
124-
Protect: data.Protect.ValueBoolPointer(),
125-
}
126-
127-
result, err := r.client.CreateCluster(ctx, attrs)
129+
result, err := r.client.CreateCluster(ctx, data.CreateAttributes())
128130
if err != nil {
129131
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create cluster, got error: %s", err))
130132
return
131133
}
132134

133135
tflog.Trace(ctx, "created a cluster")
134136

135-
data.Name = types.StringValue(result.CreateCluster.Name)
136-
data.Handle = types.StringPointerValue(result.CreateCluster.Handle)
137-
data.Id = types.StringValue(result.CreateCluster.ID)
138-
data.Protect = types.BoolPointerValue(result.CreateCluster.Protect)
139-
data.InseredAt = types.StringPointerValue(result.CreateCluster.InsertedAt)
140-
141137
if model.IsCloud(data.Cloud.ValueString(), model.CloudBYOK) {
142138
if result.CreateCluster.DeployToken == nil {
143139
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to fetch cluster deploy token"))
@@ -159,6 +155,7 @@ func (r *clusterResource) Create(ctx context.Context, req resource.CreateRequest
159155
tflog.Trace(ctx, "installed the cluster operator")
160156
}
161157

158+
data.FromCreate(result)
162159
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
163160
}
164161

@@ -175,12 +172,7 @@ func (r *clusterResource) Read(ctx context.Context, req resource.ReadRequest, re
175172
return
176173
}
177174

178-
data.Id = types.StringValue(result.Cluster.ID)
179-
data.InseredAt = types.StringPointerValue(result.Cluster.InsertedAt)
180-
data.Name = types.StringValue(result.Cluster.Name)
181-
data.Handle = types.StringPointerValue(result.Cluster.Handle)
182-
data.Protect = types.BoolPointerValue(result.Cluster.Protect)
183-
175+
data.From(result.Cluster)
184176
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
185177
}
186178

@@ -191,20 +183,12 @@ func (r *clusterResource) Update(ctx context.Context, req resource.UpdateRequest
191183
return
192184
}
193185

194-
attrs := console.ClusterUpdateAttributes{
195-
Handle: data.Handle.ValueStringPointer(),
196-
Protect: data.Protect.ValueBoolPointer(),
197-
}
198-
199-
result, err := r.client.UpdateCluster(ctx, data.Id.ValueString(), attrs)
186+
_, err := r.client.UpdateCluster(ctx, data.Id.ValueString(), data.UpdateAttributes())
200187
if err != nil {
201188
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update cluster, got error: %s", err))
202189
return
203190
}
204191

205-
data.Handle = types.StringPointerValue(result.UpdateCluster.Handle)
206-
data.Protect = types.BoolPointerValue(result.UpdateCluster.Protect)
207-
208192
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
209193
}
210194

internal/resource/provider.go

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"terraform-provider-plural/internal/client"
88
"terraform-provider-plural/internal/model"
99

10+
"github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator"
1011
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
1112
"github.com/hashicorp/terraform-plugin-framework/path"
1213
"github.com/hashicorp/terraform-plugin-framework/resource"
@@ -41,25 +42,33 @@ func (r *providerResource) Schema(_ context.Context, _ resource.SchemaRequest, r
4142
"id": schema.StringAttribute{
4243
Computed: true,
4344
MarkdownDescription: "Internal identifier of this provider.",
44-
PlanModifiers: []planmodifier.String{
45-
stringplanmodifier.UseStateForUnknown(),
46-
},
45+
PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()},
46+
},
47+
"editable": schema.BoolAttribute{
48+
MarkdownDescription: "Whether this provider is editable.",
49+
Computed: true,
4750
},
4851
"name": schema.StringAttribute{
4952
MarkdownDescription: "Human-readable name of this provider. Globally unique.",
5053
Required: true,
54+
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
5155
},
5256
"namespace": schema.StringAttribute{
5357
MarkdownDescription: "The namespace the Cluster API resources are deployed into.",
54-
Required: true,
58+
Optional: true,
59+
Computed: true,
60+
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplaceIfConfigured()},
5561
},
5662
"cloud": schema.StringAttribute{
5763
MarkdownDescription: "The name of the cloud service for this provider.",
5864
Required: true,
65+
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
5966
Validators: []validator.String{stringvalidator.OneOfCaseInsensitive(
6067
model.CloudAWS.String(), model.CloudAzure.String(), model.CloudGCP.String())},
6168
},
6269
"cloud_settings": schema.SingleNestedAttribute{
70+
MarkdownDescription: "Cloud-specific settings for a provider.",
71+
Required: true,
6372
Attributes: map[string]schema.Attribute{
6473
"aws": schema.SingleNestedAttribute{
6574
Optional: true,
@@ -75,6 +84,12 @@ func (r *providerResource) Schema(_ context.Context, _ resource.SchemaRequest, r
7584
Sensitive: true,
7685
},
7786
},
87+
Validators: []validator.Object{
88+
objectvalidator.ExactlyOneOf(
89+
path.MatchRelative().AtParent().AtName("azure"),
90+
path.MatchRelative().AtParent().AtName("gcp"),
91+
),
92+
},
7893
},
7994
"azure": schema.SingleNestedAttribute{
8095
MarkdownDescription: "Azure cloud settings that will be used by this provider to create clusters.",
@@ -101,6 +116,12 @@ func (r *providerResource) Schema(_ context.Context, _ resource.SchemaRequest, r
101116
Sensitive: true,
102117
},
103118
},
119+
Validators: []validator.Object{
120+
objectvalidator.ExactlyOneOf(
121+
path.MatchRelative().AtParent().AtName("aws"),
122+
path.MatchRelative().AtParent().AtName("gcp"),
123+
),
124+
},
104125
},
105126
"gcp": schema.SingleNestedAttribute{
106127
Optional: true,
@@ -111,10 +132,14 @@ func (r *providerResource) Schema(_ context.Context, _ resource.SchemaRequest, r
111132
Sensitive: true,
112133
},
113134
},
135+
Validators: []validator.Object{
136+
objectvalidator.ExactlyOneOf(
137+
path.MatchRelative().AtParent().AtName("aws"),
138+
path.MatchRelative().AtParent().AtName("azure"),
139+
),
140+
},
114141
},
115142
},
116-
MarkdownDescription: "Cloud-specific settings for a provider.",
117-
Required: true,
118143
},
119144
},
120145
}
@@ -145,7 +170,7 @@ func (r *providerResource) Create(ctx context.Context, req resource.CreateReques
145170
return
146171
}
147172

148-
result, err := r.client.CreateClusterProvider(ctx, data.Attributes())
173+
result, err := r.client.CreateClusterProvider(ctx, data.CreateAttributes())
149174
if err != nil {
150175
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create provider, got error: %s", err))
151176
return

0 commit comments

Comments
 (0)