Skip to content

Commit c73de13

Browse files
committed
review changes
1 parent c2c152b commit c73de13

File tree

5 files changed

+82
-92
lines changed

5 files changed

+82
-92
lines changed

docs/resources/modelserving_token.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ resource "stackit_modelserving_token" "example" {
6969
- `description` (String) The description of the model serving auth token.
7070
- `region` (String) Region to which the model serving auth token is associated. If not defined, the provider region is used
7171
- `rotate_when_changed` (Map of String) A map of arbitrary key/value pairs that will force recreation of the token when they change, enabling token rotation based on external conditions such as a rotating timestamp. Changing this forces a new resource to be created.
72-
- `ttl_duration` (String) The TTL duration of the model serving auth token.
72+
- `ttl_duration` (String) The TTL duration of the model serving auth token. E.g. 5h30m40s
7373

7474
### Read-Only
7575

76-
- `content` (String) Content of the model serving auth token.
77-
- `id` (String) Terraform's internal data source. ID. It is structured as "`project_id`,`zone_id`,`token_id`".
76+
- `id` (String) Terraform's internal data source. ID. It is structured as "`project_id`,`region`,`token_id`".
7877
- `state` (String) State of the model serving auth token.
78+
- `token` (String, Sensitive) Content of the model serving auth token.
7979
- `token_id` (String) The model serving auth token ID.
8080
- `valid_until` (String) The time until the model serving auth token is valid.

stackit/internal/services/modelserving/modelserving_acc_test.go

Lines changed: 56 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ package modelserving_test
33
import (
44
"context"
55
"fmt"
6+
"github.com/stackitcloud/stackit-sdk-go/core/utils"
67
"strings"
78
"testing"
89

910
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
1011
"github.com/hashicorp/terraform-plugin-testing/terraform"
1112
"github.com/stackitcloud/stackit-sdk-go/core/config"
1213
"github.com/stackitcloud/stackit-sdk-go/services/modelserving"
14+
"github.com/stackitcloud/stackit-sdk-go/services/modelserving/wait"
1315
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
1416
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
1517
)
@@ -46,7 +48,7 @@ func inputTokenConfig(name, description string) string {
4648
}
4749

4850
func TestAccModelServingTokenResource(t *testing.T) {
49-
resource.ParallelTest(t, resource.TestCase{
51+
resource.Test(t, resource.TestCase{
5052
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
5153
CheckDestroy: testAccCheckModelServingTokenDestroy,
5254
Steps: []resource.TestStep{
@@ -57,47 +59,15 @@ func TestAccModelServingTokenResource(t *testing.T) {
5759
tokenResource["description"],
5860
),
5961
Check: resource.ComposeAggregateTestCheckFunc(
60-
resource.TestCheckResourceAttr(
61-
"stackit_modelserving_token.token",
62-
"project_id",
63-
tokenResource["project_id"],
64-
),
65-
resource.TestCheckResourceAttr(
66-
"stackit_modelserving_token.token",
67-
"region",
68-
tokenResource["region"],
69-
),
70-
resource.TestCheckResourceAttr(
71-
"stackit_modelserving_token.token",
72-
"name",
73-
tokenResource["name"],
74-
),
75-
resource.TestCheckResourceAttr(
76-
"stackit_modelserving_token.token",
77-
"description",
78-
tokenResource["description"],
79-
),
80-
resource.TestCheckResourceAttr(
81-
"stackit_modelserving_token.token",
82-
"ttl_duration",
83-
tokenResource["ttl_duration"],
84-
),
85-
resource.TestCheckResourceAttrSet(
86-
"stackit_modelserving_token.token",
87-
"token_id",
88-
),
89-
resource.TestCheckResourceAttrSet(
90-
"stackit_modelserving_token.token",
91-
"state",
92-
),
93-
resource.TestCheckResourceAttrSet(
94-
"stackit_modelserving_token.token",
95-
"valid_until",
96-
),
97-
resource.TestCheckResourceAttrSet(
98-
"stackit_modelserving_token.token",
99-
"content",
100-
),
62+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "project_id", tokenResource["project_id"]),
63+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "region", tokenResource["region"]),
64+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "name", tokenResource["name"]),
65+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "description", tokenResource["description"]),
66+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "ttl_duration", tokenResource["ttl_duration"]),
67+
resource.TestCheckResourceAttrSet("stackit_modelserving_token.token", "token_id"),
68+
resource.TestCheckResourceAttrSet("stackit_modelserving_token.token", "state"),
69+
resource.TestCheckResourceAttrSet("stackit_modelserving_token.token", "valid_until"),
70+
resource.TestCheckResourceAttrSet("stackit_modelserving_token.token", "token"),
10171
),
10272
},
10373
// Update
@@ -107,38 +77,13 @@ func TestAccModelServingTokenResource(t *testing.T) {
10777
tokenResource["description_updated"],
10878
),
10979
Check: resource.ComposeAggregateTestCheckFunc(
110-
resource.TestCheckResourceAttr(
111-
"stackit_modelserving_token.token",
112-
"project_id",
113-
tokenResource["project_id"],
114-
),
115-
resource.TestCheckResourceAttr(
116-
"stackit_modelserving_token.token",
117-
"region",
118-
tokenResource["region"],
119-
),
120-
resource.TestCheckResourceAttr(
121-
"stackit_modelserving_token.token",
122-
"name",
123-
tokenResource["name"],
124-
),
125-
resource.TestCheckResourceAttr(
126-
"stackit_modelserving_token.token",
127-
"description",
128-
tokenResource["description_updated"],
129-
),
130-
resource.TestCheckResourceAttrSet(
131-
"stackit_modelserving_token.token",
132-
"token_id",
133-
),
134-
resource.TestCheckResourceAttrSet(
135-
"stackit_modelserving_token.token",
136-
"state",
137-
),
138-
resource.TestCheckResourceAttrSet(
139-
"stackit_modelserving_token.token",
140-
"valid_until",
141-
),
80+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "project_id", tokenResource["project_id"]),
81+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "region", tokenResource["region"]),
82+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "name", tokenResource["name"]),
83+
resource.TestCheckResourceAttr("stackit_modelserving_token.token", "description", tokenResource["description_updated"]),
84+
resource.TestCheckResourceAttrSet("stackit_modelserving_token.token", "token_id"),
85+
resource.TestCheckResourceAttrSet("stackit_modelserving_token.token", "state"),
86+
resource.TestCheckResourceAttrSet("stackit_modelserving_token.token", "valid_until"),
14287
),
14388
},
14489
// Deletion is done by the framework implicitly
@@ -148,36 +93,66 @@ func TestAccModelServingTokenResource(t *testing.T) {
14893

14994
func testAccCheckModelServingTokenDestroy(s *terraform.State) error {
15095
ctx := context.Background()
151-
15296
var client *modelserving.APIClient
15397
var err error
98+
15499
if testutil.ModelServingCustomEndpoint == "" {
155100
client, err = modelserving.NewAPIClient()
156101
} else {
157102
client, err = modelserving.NewAPIClient(
158103
config.WithEndpoint(testutil.ModelServingCustomEndpoint),
159104
)
160105
}
106+
161107
if err != nil {
162108
return fmt.Errorf("creating client: %w", err)
163109
}
164110

111+
tokensToDestroy := []string{}
165112
for _, rs := range s.RootModule().Resources {
166113
if rs.Type != "stackit_modelserving_token" {
167114
continue
168115
}
169-
// Token terraform ID: "[projectId],[region],[tokenId]"
116+
117+
// Token terraform ID: "[project_id],[region],[token_id]"
170118
idParts := strings.Split(rs.Primary.ID, core.Separator)
171119
if len(idParts) != 3 {
172120
return fmt.Errorf("invalid ID: %s", rs.Primary.ID)
173121
}
174-
tokenId := idParts[2]
175-
176-
_, err := client.GetToken(ctx, testutil.Region, testutil.ProjectId, tokenId).Execute()
177-
if err != nil {
178-
return fmt.Errorf("token %s still exists", tokenId)
122+
if len(idParts[2]) != 0 {
123+
tokensToDestroy = append(tokensToDestroy, idParts[2])
179124
}
180125
}
181126

127+
if len(tokensToDestroy) == 0 {
128+
return nil
129+
}
130+
131+
tokensResp, err := client.ListTokens(ctx, testutil.Region, testutil.ProjectId).Execute()
132+
if err != nil {
133+
return fmt.Errorf("getting tokensResp: %w", err)
134+
}
135+
136+
if tokensResp.Tokens == nil || (tokensResp.Tokens != nil && len(*tokensResp.Tokens) == 0) {
137+
fmt.Print("No tokens found for project \n")
138+
return nil
139+
}
140+
141+
items := *tokensResp.Tokens
142+
for i := range items {
143+
if items[i].Name == nil {
144+
continue
145+
}
146+
if utils.Contains(tokensToDestroy, *items[i].Name) {
147+
_, err := client.DeleteToken(ctx, testutil.Region, testutil.ProjectId, *items[i].Id).Execute()
148+
if err != nil {
149+
return fmt.Errorf("destroying token %s during CheckDestroy: %w", *items[i].Name, err)
150+
}
151+
_, err = wait.DeleteModelServingWaitHandler(ctx, client, testutil.Region, testutil.ProjectId, *items[i].Id).WaitWithContext(ctx)
152+
if err != nil {
153+
return fmt.Errorf("destroying token %s during CheckDestroy: waiting for deletion %w", *items[i].Name, err)
154+
}
155+
}
156+
}
182157
return nil
183158
}

stackit/internal/services/modelserving/token/resource.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
78
"net/http"
9+
"regexp"
810
"strings"
911
"time"
1012

@@ -49,7 +51,7 @@ type Model struct {
4951
State types.String `tfsdk:"state"`
5052
ValidUntil types.String `tfsdk:"valid_until"`
5153
TTLDuration types.String `tfsdk:"ttl_duration"`
52-
Content types.String `tfsdk:"content"`
54+
Token types.String `tfsdk:"token"`
5355
// RotateWhenChanged is a map of arbitrary key/value pairs that will force
5456
// recreation of the token when they change, enabling token rotation based on
5557
// external conditions such as a rotating timestamp. Changing this forces a new
@@ -190,7 +192,7 @@ func (r *tokenResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
190192
Description: "Model Serving Auth Token Resource schema.\n\n" + markdownDescription,
191193
Attributes: map[string]schema.Attribute{
192194
"id": schema.StringAttribute{
193-
Description: "Terraform's internal data source. ID. It is structured as \"`project_id`,`zone_id`,`token_id`\".",
195+
Description: "Terraform's internal data source. ID. It is structured as \"`project_id`,`region`,`token_id`\".",
194196
Computed: true,
195197
},
196198
"project_id": schema.StringAttribute{
@@ -219,7 +221,7 @@ func (r *tokenResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
219221
},
220222
},
221223
"ttl_duration": schema.StringAttribute{
222-
Description: "The TTL duration of the model serving auth token.",
224+
Description: "The TTL duration of the model serving auth token. E.g. 5h30m40s",
223225
Required: false,
224226
Optional: true,
225227
PlanModifiers: []planmodifier.String{
@@ -242,18 +244,27 @@ func (r *tokenResource) Schema(_ context.Context, _ resource.SchemaRequest, resp
242244
Description: "The description of the model serving auth token.",
243245
Required: false,
244246
Optional: true,
247+
Validators: []validator.String{
248+
stringvalidator.LengthBetween(1, 2000),
249+
stringvalidator.RegexMatches(regexp.MustCompile(`^[0-9a-zA-Z\s.:\/\-]+$`), ""),
250+
},
245251
},
246252
"name": schema.StringAttribute{
247253
Description: "Name of the model serving auth token.",
248254
Required: true,
255+
Validators: []validator.String{
256+
stringvalidator.LengthBetween(1, 200),
257+
stringvalidator.RegexMatches(regexp.MustCompile(`^[0-9a-zA-Z\s_-]+$`), ""),
258+
},
249259
},
250260
"state": schema.StringAttribute{
251261
Description: "State of the model serving auth token.",
252262
Computed: true,
253263
},
254-
"content": schema.StringAttribute{
264+
"token": schema.StringAttribute{
255265
Description: "Content of the model serving auth token.",
256266
Computed: true,
267+
Sensitive: true,
257268
},
258269
"valid_until": schema.StringAttribute{
259270
Description: "The time until the model serving auth token is valid.",
@@ -600,7 +611,7 @@ func mapCreateResponse(tokenCreateResp *modelserving.CreateTokenResponse, waitRe
600611
model.Name = types.StringPointerValue(token.Name)
601612
model.State = types.StringPointerValue(waitResp.Token.State)
602613
model.ValidUntil = validUntil
603-
model.Content = types.StringPointerValue(token.Content)
614+
model.Token = types.StringPointerValue(token.Content)
604615
model.Description = types.StringPointerValue(token.Description)
605616

606617
return nil
@@ -630,7 +641,7 @@ func mapToken(token *modelserving.Token, model, state *Model) error {
630641
model.State = types.StringPointerValue(token.State)
631642
model.ValidUntil = validUntil
632643
model.Description = types.StringPointerValue(token.Description)
633-
model.Content = state.Content
644+
model.Token = state.Token
634645

635646
return nil
636647
}

stackit/internal/services/modelserving/token/resource_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ func TestMapCreateTokenFields(t *testing.T) {
199199
Description: types.StringValue("desc"),
200200
State: types.StringValue("active"),
201201
ValidUntil: types.StringValue("2099-01-01T00:00:00Z"),
202-
Content: types.StringValue("content"),
202+
Token: types.StringValue("content"),
203203
RotateWhenChanged: types.MapNull(types.StringType),
204204
},
205205
isValid: true,

stackit/internal/testutil/testutil.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,11 @@ func MariaDBProviderConfig() string {
181181

182182
func ModelServingProviderConfig() string {
183183
if ModelServingCustomEndpoint == "" {
184-
return `provider "stackit" {}`
184+
return `
185+
provider "stackit" {
186+
region = "eu01"
187+
}
188+
`
185189
}
186190
return fmt.Sprintf(`
187191
provider "stackit" {

0 commit comments

Comments
 (0)