Skip to content

Commit ce0ae07

Browse files
yfodilremyleone
andauthored
feat(account): add account project resource (#1376)
Co-authored-by: Rémy Léone <[email protected]>
1 parent 3e84b5a commit ce0ae07

8 files changed

+979
-3
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/hashicorp/terraform-plugin-log v0.4.1
1313
github.com/hashicorp/terraform-plugin-sdk/v2 v2.17.0
1414
github.com/robfig/cron/v3 v3.0.1
15-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9.0.20220707130308-7ec0786bddf2
15+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9.0.20220713095144-987a16e8bbc0
1616
github.com/stretchr/testify v1.8.0
1717
)
1818

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,8 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:
254254
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
255255
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
256256
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
257-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9.0.20220707130308-7ec0786bddf2 h1:whbV5sKu3tYwN11SGjH1jGQb2RxB4gCCeL9KRKfPwmg=
258-
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9.0.20220707130308-7ec0786bddf2/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
257+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9.0.20220713095144-987a16e8bbc0 h1:Wk46C3vB2veB2dyguZZZ/MDWlrBuUwu3KAVI7OlTTX0=
258+
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.9.0.20220713095144-987a16e8bbc0/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
259259
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
260260
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
261261
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=

scaleway/helpers_account.go

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package scaleway
33
import (
44
"time"
55

6+
accountV2 "github.com/scaleway/scaleway-sdk-go/api/account/v2"
67
account "github.com/scaleway/scaleway-sdk-go/api/account/v2alpha1"
78
)
89

@@ -15,3 +16,9 @@ func accountAPI(m interface{}) *account.API {
1516
meta := m.(*Meta)
1617
return account.NewAPI(meta.scwClient)
1718
}
19+
20+
// accountV2API supports projects.
21+
func accountV2API(m interface{}) *accountV2.API {
22+
meta := m.(*Meta)
23+
return accountV2.NewAPI(meta.scwClient)
24+
}

scaleway/provider.go

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func addBetaResources(provider *schema.Provider) {
3737
"scaleway_iam_group": resourceScalewayIamGroup(),
3838
"scaleway_iam_policy": resourceScalewayIamPolicy(),
3939
"scaleway_iam_ssh_key": resourceScalewayIamSSKKey(),
40+
"scaleway_account_project": resourceScalewayAccountProject(),
4041
}
4142
betaDataSources := map[string]*schema.Resource{
4243
"scaleway_iam_ssh_key": dataSourceScalewayIamSSHKey(),

scaleway/resource_account_project.go

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package scaleway
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
accountV2 "github.com/scaleway/scaleway-sdk-go/api/account/v2"
9+
"github.com/scaleway/scaleway-sdk-go/scw"
10+
)
11+
12+
func resourceScalewayAccountProject() *schema.Resource {
13+
return &schema.Resource{
14+
CreateContext: resourceScalewayAccountProjectCreate,
15+
ReadContext: resourceScalewayAccountProjectRead,
16+
UpdateContext: resourceScalewayAccountProjectUpdate,
17+
DeleteContext: resourceScalewayAccountProjectDelete,
18+
Importer: &schema.ResourceImporter{
19+
StateContext: schema.ImportStatePassthroughContext,
20+
},
21+
SchemaVersion: 0,
22+
Schema: map[string]*schema.Schema{
23+
"name": {
24+
Type: schema.TypeString,
25+
Computed: true,
26+
Optional: true,
27+
Description: "The name of the project",
28+
},
29+
"description": {
30+
Type: schema.TypeString,
31+
Optional: true,
32+
Description: "Description of the project",
33+
},
34+
"created_at": {
35+
Type: schema.TypeString,
36+
Computed: true,
37+
Description: "The date and time of the creation of the Project (Format ISO 8601)",
38+
},
39+
"updated_at": {
40+
Type: schema.TypeString,
41+
Computed: true,
42+
Description: "The date and time of the last update of the Project (Format ISO 8601)",
43+
},
44+
"organization_id": organizationIDSchema(),
45+
},
46+
}
47+
}
48+
49+
func resourceScalewayAccountProjectCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
50+
accountAPI := accountV2API(meta)
51+
52+
res, err := accountAPI.CreateProject(&accountV2.CreateProjectRequest{
53+
Name: expandOrGenerateString(d.Get("name"), "project-"),
54+
Description: expandStringPtr(d.Get("description").(string)),
55+
}, scw.WithContext(ctx))
56+
if err != nil {
57+
return diag.FromErr(err)
58+
}
59+
60+
d.SetId(res.ID)
61+
62+
return resourceScalewayAccountProjectRead(ctx, d, meta)
63+
}
64+
65+
func resourceScalewayAccountProjectRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
66+
accountAPI := accountV2API(meta)
67+
res, err := accountAPI.GetProject(&accountV2.GetProjectRequest{
68+
ProjectID: d.Id(),
69+
}, scw.WithContext(ctx))
70+
if err != nil {
71+
if is404Error(err) {
72+
d.SetId("")
73+
return nil
74+
}
75+
return diag.FromErr(err)
76+
}
77+
78+
_ = d.Set("name", res.Name)
79+
_ = d.Set("description", res.Description)
80+
_ = d.Set("created_at", flattenTime(res.CreatedAt))
81+
_ = d.Set("updated_at", flattenTime(res.UpdatedAt))
82+
_ = d.Set("organization_id", res.OrganizationID)
83+
84+
return nil
85+
}
86+
87+
func resourceScalewayAccountProjectUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
88+
accountAPI := accountV2API(meta)
89+
90+
req := &accountV2.UpdateProjectRequest{
91+
ProjectID: d.Id(),
92+
}
93+
94+
hasChanged := false
95+
96+
if d.HasChange("name") {
97+
req.Name = expandStringPtr(d.Get("name"))
98+
hasChanged = true
99+
}
100+
if d.HasChange("description") {
101+
req.Description = expandStringPtr(d.Get("description"))
102+
hasChanged = true
103+
}
104+
105+
if hasChanged {
106+
_, err := accountAPI.UpdateProject(req, scw.WithContext(ctx))
107+
if err != nil {
108+
return diag.FromErr(err)
109+
}
110+
}
111+
112+
return resourceScalewayAccountProjectRead(ctx, d, meta)
113+
}
114+
115+
func resourceScalewayAccountProjectDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
116+
accountAPI := accountV2API(meta)
117+
118+
err := accountAPI.DeleteProject(&accountV2.DeleteProjectRequest{
119+
ProjectID: d.Id(),
120+
}, scw.WithContext(ctx))
121+
if err != nil && !is404Error(err) {
122+
return diag.FromErr(err)
123+
}
124+
125+
return nil
126+
}
+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package scaleway
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
9+
accountV2 "github.com/scaleway/scaleway-sdk-go/api/account/v2"
10+
"github.com/scaleway/scaleway-sdk-go/scw"
11+
)
12+
13+
func init() {
14+
if !terraformBetaEnabled {
15+
return
16+
}
17+
resource.AddTestSweepers("scaleway_account_project", &resource.Sweeper{
18+
Name: "scaleway_account_project",
19+
F: testSweepAccountproject,
20+
})
21+
}
22+
23+
func testSweepAccountproject(_ string) error {
24+
return sweep(func(scwClient *scw.Client) error {
25+
accountAPI := accountV2.NewAPI(scwClient)
26+
27+
l.Debugf("sweeper: destroying the project")
28+
29+
listProjects, err := accountAPI.ListProjects(&accountV2.ListProjectsRequest{})
30+
if err != nil {
31+
return fmt.Errorf("failed to list projects: %w", err)
32+
}
33+
for _, project := range listProjects.Projects {
34+
if project.Name == "default" {
35+
continue
36+
}
37+
err = accountAPI.DeleteProject(&accountV2.DeleteProjectRequest{
38+
ProjectID: project.ID,
39+
})
40+
if err != nil {
41+
return fmt.Errorf("failed to delete project: %w", err)
42+
}
43+
}
44+
return nil
45+
})
46+
}
47+
48+
func TestAccScalewayAccountProject_Basic(t *testing.T) {
49+
SkipBetaTest(t)
50+
tt := NewTestTools(t)
51+
defer tt.Cleanup()
52+
resource.ParallelTest(t, resource.TestCase{
53+
ProviderFactories: tt.ProviderFactories,
54+
CheckDestroy: testAccCheckScalewayAccountProjectDestroy(tt),
55+
Steps: []resource.TestStep{
56+
{
57+
Config: `
58+
resource "scaleway_account_project" "main" {
59+
name = "tf_tests_project_basic"
60+
description = "a description"
61+
}
62+
`,
63+
Check: resource.ComposeTestCheckFunc(
64+
testAccCheckScalewayAccountProjectExists(tt, "scaleway_account_project.main"),
65+
resource.TestCheckResourceAttr("scaleway_account_project.main", "name", "tf_tests_project_basic"),
66+
resource.TestCheckResourceAttr("scaleway_account_project.main", "description", "a description"),
67+
),
68+
},
69+
{
70+
Config: `
71+
resource "scaleway_account_project" "main" {
72+
name = "tf_tests_project_basic_rename"
73+
description = "another description"
74+
}
75+
`,
76+
Check: resource.ComposeTestCheckFunc(
77+
testAccCheckScalewayAccountProjectExists(tt, "scaleway_account_project.main"),
78+
resource.TestCheckResourceAttr("scaleway_account_project.main", "name", "tf_tests_project_basic_rename"),
79+
resource.TestCheckResourceAttr("scaleway_account_project.main", "description", "another description"),
80+
),
81+
},
82+
},
83+
})
84+
}
85+
86+
func TestAccScalewayAccountProject_NoUpdate(t *testing.T) {
87+
SkipBetaTest(t)
88+
tt := NewTestTools(t)
89+
defer tt.Cleanup()
90+
resource.ParallelTest(t, resource.TestCase{
91+
ProviderFactories: tt.ProviderFactories,
92+
CheckDestroy: testAccCheckScalewayAccountProjectDestroy(tt),
93+
Steps: []resource.TestStep{
94+
{
95+
Config: `
96+
resource "scaleway_account_project" "main" {
97+
name = "tf_tests_project_noupdate"
98+
}
99+
`,
100+
Check: resource.ComposeTestCheckFunc(
101+
testAccCheckScalewayAccountProjectExists(tt, "scaleway_account_project.main"),
102+
),
103+
},
104+
{
105+
Config: `
106+
resource "scaleway_account_project" "main" {
107+
name = "tf_tests_project_noupdate"
108+
}
109+
`,
110+
Check: resource.ComposeTestCheckFunc(
111+
testAccCheckScalewayAccountProjectExists(tt, "scaleway_account_project.main"),
112+
),
113+
},
114+
},
115+
})
116+
}
117+
118+
func testAccCheckScalewayAccountProjectExists(tt *TestTools, name string) resource.TestCheckFunc {
119+
return func(s *terraform.State) error {
120+
rs, ok := s.RootModule().Resources[name]
121+
if !ok {
122+
return fmt.Errorf("resource not found: %s", name)
123+
}
124+
125+
accountAPI := accountV2API(tt.Meta)
126+
127+
_, err := accountAPI.GetProject(&accountV2.GetProjectRequest{
128+
ProjectID: rs.Primary.ID,
129+
})
130+
if err != nil {
131+
return fmt.Errorf("could not find project: %w", err)
132+
}
133+
134+
return nil
135+
}
136+
}
137+
138+
func testAccCheckScalewayAccountProjectDestroy(tt *TestTools) resource.TestCheckFunc {
139+
return func(s *terraform.State) error {
140+
for _, rs := range s.RootModule().Resources {
141+
if rs.Type != "scaleway_account_project" {
142+
continue
143+
}
144+
145+
accountAPI := accountV2API(tt.Meta)
146+
147+
_, err := accountAPI.GetProject(&accountV2.GetProjectRequest{
148+
ProjectID: rs.Primary.ID,
149+
})
150+
151+
// If no error resource still exist
152+
if err == nil {
153+
return fmt.Errorf("resource %s(%s) still exist", rs.Type, rs.Primary.ID)
154+
}
155+
156+
// Unexpected api error we return it
157+
if !is404Error(err) {
158+
return err
159+
}
160+
}
161+
162+
return nil
163+
}
164+
}

0 commit comments

Comments
 (0)