Skip to content

Commit 498907b

Browse files
KenSpurkfcampbell
andauthored
feat: Ability to Manage Codespaces Secrets (#1729)
* add github_codespaces_secret * use repository as repoName * add github_codespaces_organization_secret * add github_codespaces_user_secret * fix version * add docs * fix id conversion * add codespaces_*public_key data source * switch back to use of name/full_name * update org test * update repo test * remove user secret visibiltiy prop & update tests --------- Co-authored-by: Keegan Campbell <me@kfcampbell.com>
1 parent 37783e2 commit 498907b

29 files changed

+2333
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package github
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
7+
)
8+
9+
func dataSourceGithubCodespacesOrganizationPublicKey() *schema.Resource {
10+
return &schema.Resource{
11+
Read: dataSourceGithubCodespacesOrganizationPublicKeyRead,
12+
13+
Schema: map[string]*schema.Schema{
14+
"key_id": {
15+
Type: schema.TypeString,
16+
Computed: true,
17+
},
18+
"key": {
19+
Type: schema.TypeString,
20+
Computed: true,
21+
},
22+
},
23+
}
24+
}
25+
26+
func dataSourceGithubCodespacesOrganizationPublicKeyRead(d *schema.ResourceData, meta interface{}) error {
27+
err := checkOrganization(meta)
28+
if err != nil {
29+
return err
30+
}
31+
32+
client := meta.(*Owner).v3client
33+
owner := meta.(*Owner).name
34+
35+
ctx := context.Background()
36+
37+
publicKey, _, err := client.Codespaces.GetOrgPublicKey(ctx, owner)
38+
if err != nil {
39+
return err
40+
}
41+
42+
d.SetId(publicKey.GetKeyID())
43+
d.Set("key_id", publicKey.GetKeyID())
44+
d.Set("key", publicKey.GetKey())
45+
46+
return nil
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package github
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
7+
)
8+
9+
func TestAccGithubCodespacesOrganizationPublicKeyDataSource(t *testing.T) {
10+
11+
t.Run("queries an organization public key without error", func(t *testing.T) {
12+
13+
config := `
14+
data "github_codespaces_organization_public_key" "test" {}
15+
`
16+
17+
check := resource.ComposeTestCheckFunc(
18+
resource.TestCheckResourceAttrSet(
19+
"data.github_codespaces_organization_public_key.test", "key",
20+
),
21+
)
22+
23+
testCase := func(t *testing.T, mode string) {
24+
resource.Test(t, resource.TestCase{
25+
PreCheck: func() { skipUnlessMode(t, mode) },
26+
Providers: testAccProviders,
27+
Steps: []resource.TestStep{
28+
{
29+
Config: config,
30+
Check: check,
31+
},
32+
},
33+
})
34+
}
35+
36+
t.Run("with an anonymous account", func(t *testing.T) {
37+
t.Skip("anonymous account not supported for this operation")
38+
})
39+
40+
t.Run("with an individual account", func(t *testing.T) {
41+
t.Skip("individual account not supported for this operation")
42+
})
43+
44+
t.Run("with an organization account", func(t *testing.T) {
45+
testCase(t, organization)
46+
})
47+
48+
})
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package github
2+
3+
import (
4+
"context"
5+
6+
"github.com/google/go-github/v53/github"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
9+
)
10+
11+
func dataSourceGithubCodespacesOrganizationSecrets() *schema.Resource {
12+
return &schema.Resource{
13+
Read: dataSourceGithubCodespacesOrganizationSecretsRead,
14+
15+
Schema: map[string]*schema.Schema{
16+
"secrets": {
17+
Type: schema.TypeList,
18+
Computed: true,
19+
Elem: &schema.Resource{
20+
Schema: map[string]*schema.Schema{
21+
"name": {
22+
Type: schema.TypeString,
23+
Computed: true,
24+
},
25+
"visibility": {
26+
Type: schema.TypeString,
27+
Computed: true,
28+
},
29+
"created_at": {
30+
Type: schema.TypeString,
31+
Computed: true,
32+
},
33+
"updated_at": {
34+
Type: schema.TypeString,
35+
Computed: true,
36+
},
37+
},
38+
},
39+
},
40+
},
41+
}
42+
}
43+
44+
func dataSourceGithubCodespacesOrganizationSecretsRead(d *schema.ResourceData, meta interface{}) error {
45+
client := meta.(*Owner).v3client
46+
owner := meta.(*Owner).name
47+
48+
options := github.ListOptions{
49+
PerPage: 100,
50+
}
51+
52+
var all_secrets []map[string]string
53+
for {
54+
secrets, resp, err := client.Codespaces.ListOrgSecrets(context.TODO(), owner, &options)
55+
if err != nil {
56+
return err
57+
}
58+
for _, secret := range secrets.Secrets {
59+
new_secret := map[string]string{
60+
"name": secret.Name,
61+
"visibility": secret.Visibility,
62+
"created_at": secret.CreatedAt.String(),
63+
"updated_at": secret.UpdatedAt.String(),
64+
}
65+
all_secrets = append(all_secrets, new_secret)
66+
67+
}
68+
if resp.NextPage == 0 {
69+
break
70+
}
71+
options.Page = resp.NextPage
72+
}
73+
74+
d.SetId(owner)
75+
d.Set("secrets", all_secrets)
76+
77+
return nil
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package github
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
10+
)
11+
12+
func TestAccGithubCodespacesOrganizationSecretsDataSource(t *testing.T) {
13+
14+
t.Run("queries organization codespaces secrets from a repository", func(t *testing.T) {
15+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
16+
17+
config := fmt.Sprintf(`
18+
resource "github_codespaces_organization_secret" "test" {
19+
secret_name = "org_cs_secret_1_%s"
20+
plaintext_value = "foo"
21+
visibility = "private"
22+
}
23+
`, randomID)
24+
25+
config2 := config + `
26+
data "github_codespaces_organization_secrets" "test" {
27+
}
28+
`
29+
30+
check := resource.ComposeTestCheckFunc(
31+
resource.TestCheckResourceAttr("data.github_codespaces_organization_secrets.test", "secrets.#", "1"),
32+
resource.TestCheckResourceAttr("data.github_codespaces_organization_secrets.test", "secrets.0.name", strings.ToUpper(fmt.Sprintf("ORG_CS_SECRET_1_%s", randomID))),
33+
resource.TestCheckResourceAttr("data.github_codespaces_organization_secrets.test", "secrets.0.visibility", "private"),
34+
resource.TestCheckResourceAttrSet("data.github_codespaces_organization_secrets.test", "secrets.0.created_at"),
35+
resource.TestCheckResourceAttrSet("data.github_codespaces_organization_secrets.test", "secrets.0.updated_at"),
36+
)
37+
38+
testCase := func(t *testing.T, mode string) {
39+
resource.Test(t, resource.TestCase{
40+
PreCheck: func() { skipUnlessMode(t, mode) },
41+
Providers: testAccProviders,
42+
Steps: []resource.TestStep{
43+
{
44+
Config: config,
45+
Check: resource.ComposeTestCheckFunc(),
46+
},
47+
{
48+
Config: config2,
49+
Check: check,
50+
},
51+
},
52+
})
53+
}
54+
55+
t.Run("with an organization account", func(t *testing.T) {
56+
testCase(t, organization)
57+
})
58+
})
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
8+
)
9+
10+
func dataSourceGithubCodespacesPublicKey() *schema.Resource {
11+
return &schema.Resource{
12+
Read: dataSourceGithubCodespacesPublicKeyRead,
13+
14+
Schema: map[string]*schema.Schema{
15+
"repository": {
16+
Type: schema.TypeString,
17+
Required: true,
18+
},
19+
"key_id": {
20+
Type: schema.TypeString,
21+
Computed: true,
22+
},
23+
"key": {
24+
Type: schema.TypeString,
25+
Computed: true,
26+
},
27+
},
28+
}
29+
}
30+
31+
func dataSourceGithubCodespacesPublicKeyRead(d *schema.ResourceData, meta interface{}) error {
32+
repository := d.Get("repository").(string)
33+
owner := meta.(*Owner).name
34+
log.Printf("[INFO] Refreshing GitHub Codespaces Public Key from: %s/%s", owner, repository)
35+
36+
client := meta.(*Owner).v3client
37+
ctx := context.Background()
38+
39+
publicKey, _, err := client.Codespaces.GetRepoPublicKey(ctx, owner, repository)
40+
if err != nil {
41+
return err
42+
}
43+
44+
d.SetId(publicKey.GetKeyID())
45+
d.Set("key_id", publicKey.GetKeyID())
46+
d.Set("key", publicKey.GetKey())
47+
48+
return nil
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package github
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
9+
)
10+
11+
func TestAccGithubCodespacesPublicKeyDataSource(t *testing.T) {
12+
13+
randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
14+
15+
t.Run("queries a repository public key without error", func(t *testing.T) {
16+
17+
config := fmt.Sprintf(`
18+
resource "github_repository" "test" {
19+
name = "tf-acc-test-%[1]s"
20+
auto_init = true
21+
}
22+
23+
data "github_codespaces_public_key" "test" {
24+
repository = github_repository.test.id
25+
}
26+
`, randomID)
27+
28+
check := resource.ComposeTestCheckFunc(
29+
resource.TestCheckResourceAttrSet(
30+
"data.github_codespaces_public_key.test", "key",
31+
),
32+
)
33+
34+
testCase := func(t *testing.T, mode string) {
35+
resource.Test(t, resource.TestCase{
36+
PreCheck: func() { skipUnlessMode(t, mode) },
37+
Providers: testAccProviders,
38+
Steps: []resource.TestStep{
39+
{
40+
Config: config,
41+
Check: check,
42+
},
43+
},
44+
})
45+
}
46+
47+
t.Run("with an anonymous account", func(t *testing.T) {
48+
t.Skip("anonymous account not supported for this operation")
49+
})
50+
51+
t.Run("with an individual account", func(t *testing.T) {
52+
testCase(t, individual)
53+
})
54+
55+
t.Run("with an organization account", func(t *testing.T) {
56+
testCase(t, organization)
57+
})
58+
59+
})
60+
}

0 commit comments

Comments
 (0)