Skip to content

Commit d51a4a7

Browse files
authored
feat: annotate resources withSchemaVersion (#244)
1 parent 62fa89d commit d51a4a7

14 files changed

+84
-43
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,7 @@ website/vendor
3232
!command/test-fixtures/**/.terraform/
3333

3434
# Keep windows files with windows line endings
35-
*.winfile eol=crlf
35+
*.winfile eol=crlf
36+
37+
# Binary
38+
terraform-provider-coder

integration/integration_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ func setup(ctx context.Context, t *testing.T, name string) string {
164164
"CODER_ACCESS_URL=" + localURL, // Set explicitly to avoid creating try.coder.app URLs.
165165
"CODER_IN_MEMORY=true", // We don't necessarily care about real persistence here.
166166
"CODER_TELEMETRY_ENABLE=false", // Avoid creating noise.
167+
"CODER_VERBOSE=TRUE", // Debug logging.
167168
"TF_CLI_CONFIG_FILE=/tmp/integration.tfrc", // Our custom tfrc from above.
169+
"TF_LOG=DEBUG", // Debug logging in Terraform provider
168170
},
169171
Labels: map[string]string{},
170172
}, &container.HostConfig{

provider/agent.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package provider
33
import (
44
"context"
55
"fmt"
6-
"os"
76
"reflect"
87
"strings"
98

@@ -12,10 +11,14 @@ import (
1211
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1312
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1413
"golang.org/x/xerrors"
14+
15+
"github.com/coder/terraform-provider-coder/provider/helpers"
1516
)
1617

1718
func agentResource() *schema.Resource {
1819
return &schema.Resource{
20+
SchemaVersion: 1,
21+
1922
Description: "Use this resource to associate an agent.",
2023
CreateContext: func(_ context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
2124
// This should be a real authentication token!
@@ -363,7 +366,7 @@ func updateInitScript(resourceData *schema.ResourceData, i interface{}) diag.Dia
363366
if err != nil {
364367
return diag.Errorf("parse access url: %s", err)
365368
}
366-
script := os.Getenv(fmt.Sprintf("CODER_AGENT_SCRIPT_%s_%s", operatingSystem, arch))
369+
script := helpers.OptionalEnv(fmt.Sprintf("CODER_AGENT_SCRIPT_%s_%s", operatingSystem, arch))
367370
if script != "" {
368371
script = strings.ReplaceAll(script, "${ACCESS_URL}", accessURL.String())
369372
script = strings.ReplaceAll(script, "${AUTH_TYPE}", auth)

provider/app.go

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ var (
2525

2626
func appResource() *schema.Resource {
2727
return &schema.Resource{
28+
SchemaVersion: 1,
29+
2830
Description: "Use this resource to define shortcuts to access applications in a workspace.",
2931
CreateContext: func(c context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {
3032
resourceData.SetId(uuid.NewString())

provider/env.go

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212

1313
func envResource() *schema.Resource {
1414
return &schema.Resource{
15+
SchemaVersion: 1,
16+
1517
Description: `Use this resource to set an environment variable in a workspace. Note that this resource cannot be used to overwrite existing environment variables set on the "coder_agent" resource.`,
1618
CreateContext: func(_ context.Context, rd *schema.ResourceData, _ interface{}) diag.Diagnostics {
1719
rd.SetId(uuid.NewString())

provider/externalauth.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ package provider
33
import (
44
"context"
55
"fmt"
6-
"os"
76

87
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
98
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
10+
"github.com/coder/terraform-provider-coder/provider/helpers"
1011
)
1112

1213
// externalAuthDataSource returns a schema for an external authentication data source.
1314
func externalAuthDataSource() *schema.Resource {
1415
return &schema.Resource{
16+
SchemaVersion: 1,
17+
1518
Description: "Use this data source to require users to authenticate with an external service prior to workspace creation. This can be used to pre-authenticate external services in a workspace. (e.g. gcloud, gh, docker, etc)",
1619
ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
1720
id, ok := rd.Get("id").(string)
@@ -20,7 +23,7 @@ func externalAuthDataSource() *schema.Resource {
2023
}
2124
rd.SetId(id)
2225

23-
accessToken := os.Getenv(ExternalAuthAccessTokenEnvironmentVariable(id))
26+
accessToken := helpers.OptionalEnv(ExternalAuthAccessTokenEnvironmentVariable(id))
2427
rd.Set("access_token", accessToken)
2528
return nil
2629
},

provider/gitauth.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ package provider
33
import (
44
"context"
55
"fmt"
6-
"os"
76

87
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
98
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
10+
"github.com/coder/terraform-provider-coder/provider/helpers"
1011
)
1112

1213
// gitAuthDataSource returns a schema for a Git authentication data source.
1314
func gitAuthDataSource() *schema.Resource {
1415
return &schema.Resource{
16+
SchemaVersion: 1,
17+
1518
DeprecationMessage: "Use the `coder_external_auth` data source instead.",
1619
Description: "Use this data source to require users to authenticate with a Git provider prior to workspace creation. This can be used to perform an authenticated `git clone` in startup scripts.",
1720
ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
@@ -25,7 +28,7 @@ func gitAuthDataSource() *schema.Resource {
2528
}
2629
rd.SetId(id)
2730

28-
accessToken := os.Getenv(GitAuthAccessTokenEnvironmentVariable(id))
31+
accessToken := helpers.OptionalEnv(GitAuthAccessTokenEnvironmentVariable(id))
2932
rd.Set("access_token", accessToken)
3033

3134
return nil

provider/helpers/env.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package helpers
2+
3+
import (
4+
"fmt"
5+
"os"
6+
)
7+
8+
// RequireEnv requires environment variable to be present.
9+
func RequireEnv(name string) (string, error) {
10+
val := os.Getenv(name)
11+
if val == "" {
12+
return "", fmt.Errorf("%s is required", name)
13+
}
14+
return val, nil
15+
}
16+
17+
// OptionalEnv returns the value for environment variable if it exists,
18+
// otherwise returns an empty string.
19+
func OptionalEnv(name string) string {
20+
return OptionalEnvOrDefault(name, "")
21+
}
22+
23+
// OptionalEnvOrDefault returns the value for environment variable if it exists,
24+
// otherwise returns the default value.
25+
func OptionalEnvOrDefault(name, defaultValue string) string {
26+
val := os.Getenv(name)
27+
if val == "" {
28+
return defaultValue
29+
}
30+
return val
31+
}

provider/metadata.go

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111

1212
func metadataResource() *schema.Resource {
1313
return &schema.Resource{
14+
SchemaVersion: 1,
15+
1416
Description: "Use this resource to attach metadata to a resource. They will be " +
1517
"displayed in the Coder dashboard.",
1618
CreateContext: func(c context.Context, resourceData *schema.ResourceData, i interface{}) diag.Diagnostics {

provider/parameter.go

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ type Parameter struct {
6363

6464
func parameterDataSource() *schema.Resource {
6565
return &schema.Resource{
66+
SchemaVersion: 1,
67+
6668
Description: "Use this data source to configure editable options for workspaces.",
6769
ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
6870
rd.SetId(uuid.NewString())

provider/provisioner.go

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111

1212
func provisionerDataSource() *schema.Resource {
1313
return &schema.Resource{
14+
SchemaVersion: 1,
15+
1416
Description: "Use this data source to get information about the Coder provisioner.",
1517
ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
1618
rd.SetId(uuid.NewString())

provider/script.go

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ var ScriptCRONParser = cron.NewParser(cron.Second | cron.Minute | cron.Hour | cr
1515

1616
func scriptResource() *schema.Resource {
1717
return &schema.Resource{
18+
SchemaVersion: 1,
19+
1820
Description: "Use this resource to run a script from an agent.",
1921
CreateContext: func(_ context.Context, rd *schema.ResourceData, _ interface{}) diag.Diagnostics {
2022
rd.SetId(uuid.NewString())

provider/workspace.go

+18-36
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,38 @@ package provider
33
import (
44
"context"
55
"encoding/json"
6-
"os"
76
"reflect"
87
"strconv"
98

109
"github.com/google/uuid"
1110
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1211
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
13+
"github.com/coder/terraform-provider-coder/provider/helpers"
1314
)
1415

1516
func workspaceDataSource() *schema.Resource {
1617
return &schema.Resource{
18+
SchemaVersion: 1,
19+
1720
Description: "Use this data source to get information for the active workspace build.",
1821
ReadContext: func(c context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
19-
transition := os.Getenv("CODER_WORKSPACE_TRANSITION")
20-
if transition == "" {
21-
// Default to start!
22-
transition = "start"
23-
}
22+
transition := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_TRANSITION", "start") // Default to start!
2423
_ = rd.Set("transition", transition)
24+
2525
count := 0
2626
if transition == "start" {
2727
count = 1
2828
}
2929
_ = rd.Set("start_count", count)
3030

31-
owner := os.Getenv("CODER_WORKSPACE_OWNER")
32-
if owner == "" {
33-
owner = "default"
34-
}
31+
owner := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER", "default")
3532
_ = rd.Set("owner", owner)
3633

37-
ownerEmail := os.Getenv("CODER_WORKSPACE_OWNER_EMAIL")
38-
if ownerEmail == "" {
39-
ownerEmail = "[email protected]"
40-
}
34+
ownerEmail := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER_EMAIL", "[email protected]")
4135
_ = rd.Set("owner_email", ownerEmail)
4236

43-
ownerGroupsText := os.Getenv("CODER_WORKSPACE_OWNER_GROUPS")
37+
ownerGroupsText := helpers.OptionalEnv("CODER_WORKSPACE_OWNER_GROUPS")
4438
var ownerGroups []string
4539
if ownerGroupsText != "" {
4640
err := json.Unmarshal([]byte(ownerGroupsText), &ownerGroups)
@@ -50,43 +44,31 @@ func workspaceDataSource() *schema.Resource {
5044
}
5145
_ = rd.Set("owner_groups", ownerGroups)
5246

53-
ownerName := os.Getenv("CODER_WORKSPACE_OWNER_NAME")
54-
if ownerName == "" {
55-
ownerName = "default"
56-
}
47+
ownerName := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER_NAME", "default")
5748
_ = rd.Set("owner_name", ownerName)
5849

59-
ownerID := os.Getenv("CODER_WORKSPACE_OWNER_ID")
60-
if ownerID == "" {
61-
ownerID = uuid.Nil.String()
62-
}
50+
ownerID := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_OWNER_ID", uuid.Nil.String())
6351
_ = rd.Set("owner_id", ownerID)
6452

65-
ownerOIDCAccessToken := os.Getenv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN")
53+
ownerOIDCAccessToken := helpers.OptionalEnv("CODER_WORKSPACE_OWNER_OIDC_ACCESS_TOKEN")
6654
_ = rd.Set("owner_oidc_access_token", ownerOIDCAccessToken)
6755

68-
name := os.Getenv("CODER_WORKSPACE_NAME")
69-
if name == "" {
70-
name = "default"
71-
}
56+
name := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_NAME", "default")
7257
rd.Set("name", name)
7358

74-
sessionToken := os.Getenv("CODER_WORKSPACE_OWNER_SESSION_TOKEN")
59+
sessionToken := helpers.OptionalEnv("CODER_WORKSPACE_OWNER_SESSION_TOKEN")
7560
_ = rd.Set("owner_session_token", sessionToken)
7661

77-
id := os.Getenv("CODER_WORKSPACE_ID")
78-
if id == "" {
79-
id = uuid.NewString()
80-
}
62+
id := helpers.OptionalEnvOrDefault("CODER_WORKSPACE_ID", uuid.NewString())
8163
rd.SetId(id)
8264

83-
templateID := os.Getenv("CODER_WORKSPACE_TEMPLATE_ID")
65+
templateID := helpers.OptionalEnv("CODER_WORKSPACE_TEMPLATE_ID") // FIXME switch to `helpers.RequireEnv(...)`
8466
_ = rd.Set("template_id", templateID)
8567

86-
templateName := os.Getenv("CODER_WORKSPACE_TEMPLATE_NAME")
68+
templateName := helpers.OptionalEnv("CODER_WORKSPACE_TEMPLATE_NAME") // FIXME switch to `helpers.RequireEnv(...)`
8769
_ = rd.Set("template_name", templateName)
8870

89-
templateVersion := os.Getenv("CODER_WORKSPACE_TEMPLATE_VERSION")
71+
templateVersion := helpers.OptionalEnv("CODER_WORKSPACE_TEMPLATE_VERSION") // FIXME switch to `helpers.RequireEnv(...)`
9072
_ = rd.Set("template_version", templateVersion)
9173

9274
config, valid := i.(config)

provider/workspace_tags.go

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ type WorkspaceTags struct {
1414

1515
func workspaceTagDataSource() *schema.Resource {
1616
return &schema.Resource{
17+
SchemaVersion: 1,
18+
1719
Description: "Use this data source to configure workspace tags to select provisioners.",
1820
ReadContext: func(ctx context.Context, rd *schema.ResourceData, i interface{}) diag.Diagnostics {
1921
rd.SetId(uuid.NewString())

0 commit comments

Comments
 (0)