Skip to content

Commit 277bdbf

Browse files
Added Image Share Group Token resource
1 parent f041149 commit 277bdbf

File tree

5 files changed

+324
-1
lines changed

5 files changed

+324
-1
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package consumerimagesharegrouptoken
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
5+
"github.com/hashicorp/terraform-plugin-framework/types"
6+
"github.com/linode/linodego"
7+
"github.com/linode/terraform-provider-linode/v3/linode/helper"
8+
)
9+
10+
type ResourceModel struct {
11+
ValidForShareGroupUUID types.String `tfsdk:"valid_for_sharegroup_uuid"`
12+
Label types.String `tfsdk:"label"`
13+
Token types.String `tfsdk:"token"`
14+
TokenUUID types.String `tfsdk:"token_uuid"`
15+
Status types.String `tfsdk:"status"`
16+
Created timetypes.RFC3339 `tfsdk:"created"`
17+
Updated timetypes.RFC3339 `tfsdk:"updated"`
18+
Expiry timetypes.RFC3339 `tfsdk:"expiry"`
19+
ShareGroupUUID types.String `tfsdk:"sharegroup_uuid"`
20+
ShareGroupLabel types.String `tfsdk:"sharegroup_label"`
21+
}
22+
23+
func (data *ResourceModel) FlattenImageShareGroupCreateToken(
24+
resp *linodego.ImageShareGroupCreateTokenResponse,
25+
) {
26+
data.ValidForShareGroupUUID = types.StringValue(resp.ValidForShareGroupUUID)
27+
28+
if resp.Label != "" {
29+
data.Label = types.StringValue(resp.Label)
30+
} else {
31+
data.Label = types.StringNull()
32+
}
33+
34+
data.TokenUUID = types.StringValue(resp.TokenUUID)
35+
data.Status = types.StringValue(resp.Status)
36+
data.Created = timetypes.NewRFC3339TimePointerValue(resp.Created)
37+
data.Updated = timetypes.NewRFC3339TimePointerValue(resp.Updated)
38+
data.Expiry = timetypes.NewRFC3339TimePointerValue(resp.Expiry)
39+
data.ShareGroupUUID = types.StringPointerValue(resp.ShareGroupUUID)
40+
data.ShareGroupLabel = types.StringPointerValue(resp.ShareGroupLabel)
41+
42+
// Token is only present in the API response during creation
43+
data.Token = types.StringValue(resp.Token)
44+
}
45+
46+
func (data *ResourceModel) FlattenImageShareGroupToken(
47+
token *linodego.ImageShareGroupToken,
48+
preserveKnown bool,
49+
) {
50+
// Do not touch Token here since it’s only returned at create time
51+
52+
data.ValidForShareGroupUUID = helper.KeepOrUpdateString(data.ValidForShareGroupUUID, token.ValidForShareGroupUUID, preserveKnown)
53+
54+
if token.Label != "" {
55+
data.Label = helper.KeepOrUpdateString(data.Label, token.Label, preserveKnown)
56+
} else if !preserveKnown {
57+
data.Label = types.StringNull()
58+
}
59+
60+
data.TokenUUID = helper.KeepOrUpdateString(data.TokenUUID, token.TokenUUID, preserveKnown)
61+
data.Status = helper.KeepOrUpdateString(data.Status, token.Status, preserveKnown)
62+
data.Created = helper.KeepOrUpdateValue(
63+
data.Created, timetypes.NewRFC3339TimePointerValue(token.Created), preserveKnown,
64+
)
65+
data.Updated = helper.KeepOrUpdateValue(
66+
data.Updated, timetypes.NewRFC3339TimePointerValue(token.Updated), preserveKnown,
67+
)
68+
data.Expiry = helper.KeepOrUpdateValue(
69+
data.Expiry, timetypes.NewRFC3339TimePointerValue(token.Expiry), preserveKnown,
70+
)
71+
data.ShareGroupUUID = helper.KeepOrUpdateStringPointer(data.ShareGroupUUID, token.ShareGroupUUID, preserveKnown)
72+
data.ShareGroupLabel = helper.KeepOrUpdateStringPointer(data.ShareGroupLabel, token.ShareGroupLabel, preserveKnown)
73+
}
74+
75+
func (m *ResourceModel) CopyFrom(other ResourceModel, preserveKnown bool) {
76+
m.ValidForShareGroupUUID = helper.KeepOrUpdateValue(m.ValidForShareGroupUUID, other.ValidForShareGroupUUID, preserveKnown)
77+
m.Token = helper.KeepOrUpdateValue(m.Token, other.Token, preserveKnown)
78+
m.Label = helper.KeepOrUpdateValue(m.Label, other.Label, preserveKnown)
79+
m.TokenUUID = helper.KeepOrUpdateValue(m.TokenUUID, other.TokenUUID, preserveKnown)
80+
m.Status = helper.KeepOrUpdateValue(m.Status, other.Status, preserveKnown)
81+
m.Created = helper.KeepOrUpdateValue(m.Created, other.Created, preserveKnown)
82+
m.Updated = helper.KeepOrUpdateValue(m.Updated, other.Updated, preserveKnown)
83+
m.Expiry = helper.KeepOrUpdateValue(m.Expiry, other.Expiry, preserveKnown)
84+
m.ShareGroupUUID = helper.KeepOrUpdateValue(m.ShareGroupUUID, other.ShareGroupUUID, preserveKnown)
85+
m.ShareGroupLabel = helper.KeepOrUpdateValue(m.ShareGroupLabel, other.ShareGroupLabel, preserveKnown)
86+
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package consumerimagesharegrouptoken
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/hashicorp/terraform-plugin-framework/resource"
7+
"github.com/hashicorp/terraform-plugin-framework/types"
8+
"github.com/hashicorp/terraform-plugin-log/tflog"
9+
"github.com/linode/linodego"
10+
"github.com/linode/terraform-provider-linode/v3/linode/helper"
11+
)
12+
13+
func NewResource() resource.Resource {
14+
return &Resource{
15+
BaseResource: helper.NewBaseResource(
16+
helper.BaseResourceConfig{
17+
Name: "linode_consumer_image_share_group_token",
18+
IDType: types.Int64Type,
19+
Schema: &frameworkResourceSchema,
20+
},
21+
),
22+
}
23+
}
24+
25+
type Resource struct {
26+
helper.BaseResource
27+
}
28+
29+
func (r *Resource) Create(
30+
ctx context.Context,
31+
req resource.CreateRequest,
32+
resp *resource.CreateResponse,
33+
) {
34+
tflog.Debug(ctx, "Create "+r.Config.Name)
35+
36+
var plan ResourceModel
37+
client := r.Meta.Client
38+
39+
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
40+
if resp.Diagnostics.HasError() {
41+
return
42+
}
43+
44+
createOpts := linodego.ImageShareGroupCreateTokenOptions{
45+
ValidForShareGroupUUID: plan.ValidForShareGroupUUID.ValueString(),
46+
Label: plan.Label.ValueStringPointer(),
47+
}
48+
49+
tflog.Debug(ctx, "client.ImageShareGroupCreateToken(...)", map[string]any{
50+
"options": createOpts,
51+
})
52+
53+
token, err := client.ImageShareGroupCreateToken(ctx, createOpts)
54+
if err != nil {
55+
resp.Diagnostics.AddError(
56+
"Failed to create Image Share Group Token.",
57+
err.Error(),
58+
)
59+
return
60+
}
61+
62+
plan.FlattenImageShareGroupCreateToken(token)
63+
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
64+
}
65+
66+
func (r *Resource) Read(
67+
ctx context.Context,
68+
req resource.ReadRequest,
69+
resp *resource.ReadResponse,
70+
) {
71+
tflog.Debug(ctx, "Read "+r.Config.Name)
72+
73+
client := r.Meta.Client
74+
75+
var state ResourceModel
76+
77+
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
78+
if resp.Diagnostics.HasError() {
79+
return
80+
}
81+
82+
tokenUUID := state.TokenUUID.ValueString()
83+
84+
token, err := client.ImageShareGroupGetToken(ctx, tokenUUID)
85+
if err != nil {
86+
resp.Diagnostics.AddError(
87+
"Failed to read Image Share Group Token.",
88+
err.Error(),
89+
)
90+
return
91+
}
92+
93+
state.FlattenImageShareGroupToken(token, true)
94+
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
95+
}
96+
97+
func (r *Resource) Update(
98+
ctx context.Context,
99+
req resource.UpdateRequest,
100+
resp *resource.UpdateResponse,
101+
) {
102+
tflog.Debug(ctx, "Update "+r.Config.Name)
103+
104+
client := r.Meta.Client
105+
106+
var plan ResourceModel
107+
var state ResourceModel
108+
109+
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
110+
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
111+
if resp.Diagnostics.HasError() {
112+
return
113+
}
114+
115+
tokenUUID := state.TokenUUID.ValueString()
116+
117+
var updateOpts linodego.ImageShareGroupUpdateTokenOptions
118+
shouldUpdate := false
119+
120+
if !state.Label.Equal(plan.Label) {
121+
shouldUpdate = true
122+
updateOpts.Label = plan.Label.ValueString()
123+
}
124+
125+
if shouldUpdate {
126+
tflog.Debug(ctx, "client.ImageShareGroupUpdateToken(...)", map[string]any{
127+
"options": updateOpts,
128+
})
129+
130+
token, err := client.ImageShareGroupUpdateToken(ctx, tokenUUID, updateOpts)
131+
if err != nil {
132+
resp.Diagnostics.AddError(
133+
fmt.Sprintf("Failed to update Image Share Group Token (%d).", tokenUUID),
134+
err.Error(),
135+
)
136+
return
137+
}
138+
139+
plan.FlattenImageShareGroupToken(token, false)
140+
if resp.Diagnostics.HasError() {
141+
return
142+
}
143+
}
144+
plan.CopyFrom(state, true)
145+
146+
resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...)
147+
}
148+
149+
func (r *Resource) Delete(
150+
ctx context.Context,
151+
req resource.DeleteRequest,
152+
resp *resource.DeleteResponse,
153+
) {
154+
tflog.Debug(ctx, "Delete "+r.Config.Name)
155+
156+
var state ResourceModel
157+
158+
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
159+
if resp.Diagnostics.HasError() {
160+
return
161+
}
162+
163+
tokenUUID := state.TokenUUID.ValueString()
164+
165+
client := r.Meta.Client
166+
167+
err := client.ImageShareGroupRemoveToken(ctx, tokenUUID)
168+
if err != nil {
169+
resp.Diagnostics.AddError("Failed to Delete Image Share Group Token.", err.Error())
170+
return
171+
}
172+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package consumerimagesharegrouptoken
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
5+
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
6+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
7+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
8+
)
9+
10+
var frameworkResourceSchema = schema.Schema{
11+
Attributes: map[string]schema.Attribute{
12+
"valid_for_sharegroup_uuid": schema.StringAttribute{
13+
Description: "The UUID of the Image Share Group this token is for.",
14+
Required: true,
15+
PlanModifiers: []planmodifier.String{
16+
stringplanmodifier.RequiresReplace(),
17+
},
18+
},
19+
"label": schema.StringAttribute{
20+
Description: "The label of the token.",
21+
Optional: true,
22+
},
23+
"token": schema.StringAttribute{
24+
Description: "The one-time-use token to be provided to the Share Group Producer.",
25+
Computed: true,
26+
Sensitive: true,
27+
PlanModifiers: []planmodifier.String{
28+
stringplanmodifier.UseStateForUnknown(),
29+
},
30+
},
31+
"token_uuid": schema.StringAttribute{
32+
Description: "The UUID of the token.",
33+
Computed: true,
34+
},
35+
"status": schema.StringAttribute{
36+
Description: "The status of the token.",
37+
Computed: true,
38+
},
39+
"created": schema.StringAttribute{
40+
Description: "When this token was created.",
41+
Computed: true,
42+
CustomType: timetypes.RFC3339Type{},
43+
},
44+
"updated": schema.StringAttribute{
45+
Description: "When this token was last updated.",
46+
Computed: true,
47+
CustomType: timetypes.RFC3339Type{},
48+
},
49+
"expiry": schema.StringAttribute{
50+
Description: "When this token will expire.",
51+
Computed: true,
52+
CustomType: timetypes.RFC3339Type{},
53+
},
54+
"sharegroup_uuid": schema.StringAttribute{
55+
Description: "The UUID of the Image Share Group this token is for.",
56+
Computed: true,
57+
},
58+
"sharegroup_label": schema.StringAttribute{
59+
Description: "The label of the Image Share Group this token is for.",
60+
Computed: true,
61+
},
62+
},
63+
}

linode/framework_provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package linode
22

33
import (
44
"context"
5+
"github.com/linode/terraform-provider-linode/v3/linode/consumerimagesharegrouptoken"
56

67
"github.com/hashicorp/terraform-plugin-framework/datasource"
78
"github.com/hashicorp/terraform-plugin-framework/provider"
@@ -258,6 +259,7 @@ func (p *FrameworkProvider) Resources(ctx context.Context) []func() resource.Res
258259
databasemysqlv2.NewResource,
259260
producerimagesharegroup.NewResource,
260261
producerimagesharegroupmember.NewResource,
262+
consumerimagesharegrouptoken.NewResource,
261263
}
262264
}
263265

linode/producerimagesharegroupmember/framework_models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (data *ResourceModel) FlattenImageShareGroupMember(
2222
member *linodego.ImageShareGroupMember,
2323
preserveKnown bool,
2424
) {
25-
// We do not touch ShareGroupID Token as they are not returned by the API and must be preserved as-is.
25+
// Do not touch ShareGroupID or Token as they are not returned by the API and must be preserved
2626

2727
data.Label = helper.KeepOrUpdateString(data.Label, member.Label, preserveKnown)
2828
data.TokenUUID = helper.KeepOrUpdateString(data.TokenUUID, member.TokenUUID, preserveKnown)

0 commit comments

Comments
 (0)