-
Notifications
You must be signed in to change notification settings - Fork 945
feat: Adding github_enterprise_ip_allow_list_entry resource #2649
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ErikElkins
wants to merge
33
commits into
integrations:main
Choose a base branch
from
ErikElkins:feat/enterprise-ip-allow-list
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
943df18
Adding github_enterprise_ip_allow_list_entry resource
ErikElkins eb02154
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins 935e689
Merge branch 'main' into feat/enterprise-ip-allow-list
nickfloyd 83a0055
Update github/resource_github_enterprise_ip_allow_list_entry.go
ErikElkins c3735ac
Update github/resource_github_enterprise_ip_allow_list_entry.go
ErikElkins e1b06a2
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins 833f3f1
Update github/resource_github_enterprise_ip_allow_list_entry.go
ErikElkins 60c686b
Update github/resource_github_enterprise_ip_allow_list_entry_test.go
ErikElkins f667dcc
Update github/resource_github_enterprise_ip_allow_list_entry_test.go
ErikElkins 06b2e43
Code review fixes
ErikElkins f8d8807
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins aed945b
Fixes from code review
ErikElkins a032d9d
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins b076b2a
Fixing code review comments
ErikElkins d5a1915
Update resource_github_enterprise_ip_allow_list_entry.go
ErikElkins 2511b0b
Update resource_github_enterprise_ip_allow_list_entry.go
ErikElkins 4c9ac44
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins d593d56
Update github/resource_github_enterprise_ip_allow_list_entry_test.go
ErikElkins 10de6a7
Update github/resource_github_enterprise_ip_allow_list_entry.go
ErikElkins 4474a4f
Code review changes
ErikElkins 01d61fc
Fixing config in test
ErikElkins 03d79ef
Flattening update test
ErikElkins 4e50668
Adding error handling
ErikElkins 252cfe4
Simplifying import function
ErikElkins 0369b10
Fix docs
ErikElkins 8918bb8
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins 2eb508d
Fixing code review changes
ErikElkins 85b1956
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins 5dd8ef6
Fixing lint
ErikElkins 08aa432
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins c5e2e12
Adding error handling for missing global ID
ErikElkins 43a86af
Merge branch 'main' into feat/enterprise-ip-allow-list
ErikElkins 1c87cc4
Removing two old functions
ErikElkins File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
283 changes: 283 additions & 0 deletions
283
github/resource_github_enterprise_ip_allow_list_entry.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,283 @@ | ||
| package github | ||
|
|
||
| import ( | ||
| "context" | ||
| "strings" | ||
|
|
||
| "github.com/hashicorp/terraform-plugin-log/tflog" | ||
| "github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
| "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
| "github.com/shurcooL/githubv4" | ||
| ) | ||
|
|
||
| func resourceGithubEnterpriseIpAllowListEntry() *schema.Resource { | ||
| return &schema.Resource{ | ||
| Description: "Manage a GitHub Enterprise IP Allow List Entry.", | ||
| CreateContext: resourceGithubEnterpriseIpAllowListEntryCreate, | ||
| ReadContext: resourceGithubEnterpriseIpAllowListEntryRead, | ||
| UpdateContext: resourceGithubEnterpriseIpAllowListEntryUpdate, | ||
| DeleteContext: resourceGithubEnterpriseIpAllowListEntryDelete, | ||
| Importer: &schema.ResourceImporter{ | ||
| StateContext: resourceGithubEnterpriseIpAllowListEntryImport, | ||
| }, | ||
|
|
||
| Schema: map[string]*schema.Schema{ | ||
| "enterprise_slug": { | ||
| Type: schema.TypeString, | ||
| Required: true, | ||
ErikElkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ForceNew: true, | ||
| Description: "The slug of the enterprise to apply the IP allow list entry to.", | ||
| }, | ||
| "ip": { | ||
| Type: schema.TypeString, | ||
| Required: true, | ||
ErikElkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ForceNew: true, | ||
| Description: "An IP address or range of IP addresses in CIDR notation.", | ||
| }, | ||
stevehipwell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "name": { | ||
| Type: schema.TypeString, | ||
| Optional: true, | ||
| Description: "An optional name for the IP allow list entry.", | ||
| }, | ||
| "is_active": { | ||
| Type: schema.TypeBool, | ||
| Optional: true, | ||
| Default: true, | ||
| Description: "Whether the entry is currently active.", | ||
| }, | ||
ErikElkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "created_at": { | ||
| Type: schema.TypeString, | ||
| Computed: true, | ||
| Description: "Timestamp of when the entry was created.", | ||
| }, | ||
| "updated_at": { | ||
| Type: schema.TypeString, | ||
| Computed: true, | ||
| Description: "Timestamp of when the entry was last updated.", | ||
| }, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| func resourceGithubEnterpriseIpAllowListEntryCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { | ||
| client := meta.(*Owner).v4client | ||
|
|
||
| // First, get the enterprise ID as we need it for the mutation | ||
| enterpriseSlug := d.Get("enterprise_slug").(string) | ||
| enterpriseID, err := getEnterpriseID(ctx, client, enterpriseSlug) | ||
| if err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| // Then create the IP allow list entry | ||
| var mutation struct { | ||
| CreateIpAllowListEntry struct { | ||
| IpAllowListEntry struct { | ||
| ID githubv4.String | ||
| AllowListValue githubv4.String | ||
| Name githubv4.String | ||
| IsActive githubv4.Boolean | ||
| CreatedAt githubv4.String | ||
| UpdatedAt githubv4.String | ||
| } | ||
| } `graphql:"createIpAllowListEntry(input: $input)"` | ||
| } | ||
|
|
||
| name := d.Get("name").(string) | ||
| input := githubv4.CreateIpAllowListEntryInput{ | ||
| OwnerID: githubv4.ID(enterpriseID), | ||
| AllowListValue: githubv4.String(d.Get("ip").(string)), | ||
| IsActive: githubv4.Boolean(d.Get("is_active").(bool)), | ||
| } | ||
|
|
||
| if name != "" { | ||
| input.Name = githubv4.NewString(githubv4.String(name)) | ||
| } | ||
|
|
||
| err = client.Mutate(ctx, &mutation, input, nil) | ||
| if err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| d.SetId(string(mutation.CreateIpAllowListEntry.IpAllowListEntry.ID)) | ||
|
|
||
| if err := d.Set("created_at", mutation.CreateIpAllowListEntry.IpAllowListEntry.CreatedAt); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| if err := d.Set("updated_at", mutation.CreateIpAllowListEntry.IpAllowListEntry.UpdatedAt); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func resourceGithubEnterpriseIpAllowListEntryRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { | ||
| client := meta.(*Owner).v4client | ||
|
|
||
| var query struct { | ||
| Node struct { | ||
| IpAllowListEntry struct { | ||
| ID githubv4.String | ||
| AllowListValue githubv4.String | ||
| Name githubv4.String | ||
| IsActive githubv4.Boolean | ||
| CreatedAt githubv4.String | ||
| UpdatedAt githubv4.String | ||
| Owner struct { | ||
| Enterprise struct { | ||
| Slug githubv4.String | ||
| } `graphql:"... on Enterprise"` | ||
| } | ||
| } `graphql:"... on IpAllowListEntry"` | ||
| } `graphql:"node(id: $id)"` | ||
| } | ||
|
|
||
| variables := map[string]any{ | ||
| "id": githubv4.ID(d.Id()), | ||
| } | ||
|
|
||
| err := client.Query(ctx, &query, variables) | ||
| if err != nil { | ||
| if strings.Contains(err.Error(), "Could not resolve to a node with the global id") { | ||
| tflog.Info(ctx, "Removing IP allow list entry from state because it no longer exists in GitHub", map[string]any{ | ||
| "id": d.Id(), | ||
| }) | ||
| d.SetId("") | ||
| return nil | ||
| } | ||
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| entry := query.Node.IpAllowListEntry | ||
| if err := d.Set("name", entry.Name); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| if err := d.Set("ip", entry.AllowListValue); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| if err := d.Set("is_active", entry.IsActive); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| if err := d.Set("created_at", entry.CreatedAt); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
| if err := d.Set("updated_at", entry.UpdatedAt); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func resourceGithubEnterpriseIpAllowListEntryUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { | ||
| client := meta.(*Owner).v4client | ||
|
|
||
| var mutation struct { | ||
| UpdateIpAllowListEntry struct { | ||
| IpAllowListEntry struct { | ||
| ID githubv4.String | ||
| AllowListValue githubv4.String | ||
| Name githubv4.String | ||
| IsActive githubv4.Boolean | ||
| UpdatedAt githubv4.String | ||
| } | ||
| } `graphql:"updateIpAllowListEntry(input: $input)"` | ||
| } | ||
|
|
||
| name := d.Get("name").(string) | ||
| input := githubv4.UpdateIpAllowListEntryInput{ | ||
| IPAllowListEntryID: githubv4.ID(d.Id()), | ||
| AllowListValue: githubv4.String(d.Get("ip").(string)), | ||
| IsActive: githubv4.Boolean(d.Get("is_active").(bool)), | ||
| } | ||
|
|
||
| if name != "" { | ||
| input.Name = githubv4.NewString(githubv4.String(name)) | ||
| } | ||
|
|
||
| err := client.Mutate(ctx, &mutation, input, nil) | ||
| if err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| if err := d.Set("updated_at", mutation.UpdateIpAllowListEntry.IpAllowListEntry.UpdatedAt); err != nil { | ||
| return diag.FromErr(err) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func resourceGithubEnterpriseIpAllowListEntryDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { | ||
| client := meta.(*Owner).v4client | ||
|
|
||
| var mutation struct { | ||
| DeleteIpAllowListEntry struct { | ||
| ClientMutationID githubv4.String | ||
| } `graphql:"deleteIpAllowListEntry(input: $input)"` | ||
| } | ||
|
|
||
| input := githubv4.DeleteIpAllowListEntryInput{ | ||
| IPAllowListEntryID: githubv4.ID(d.Id()), | ||
| } | ||
|
|
||
| err := client.Mutate(ctx, &mutation, input, nil) | ||
| // GraphQL will return a 200 OK if it couldn't find the global ID | ||
| if err != nil && !strings.Contains(err.Error(), "Could not resolve to a node with the global id") { | ||
| return diag.FromErr(err) | ||
ErikElkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func resourceGithubEnterpriseIpAllowListEntryImport(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { | ||
ErikElkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| client := meta.(*Owner).v4client | ||
|
|
||
| var query struct { | ||
| Node struct { | ||
| IpAllowListEntry struct { | ||
| ID githubv4.String | ||
| AllowListValue githubv4.String | ||
| Name githubv4.String | ||
| IsActive githubv4.Boolean | ||
| CreatedAt githubv4.String | ||
| UpdatedAt githubv4.String | ||
| Owner struct { | ||
| Enterprise struct { | ||
| Slug githubv4.String | ||
| } `graphql:"... on Enterprise"` | ||
| } | ||
| } `graphql:"... on IpAllowListEntry"` | ||
| } `graphql:"node(id: $id)"` | ||
| } | ||
|
|
||
| variables := map[string]any{ | ||
| "id": githubv4.ID(d.Id()), | ||
| } | ||
|
|
||
| err := client.Query(ctx, &query, variables) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| entry := query.Node.IpAllowListEntry | ||
|
|
||
| if err := d.Set("enterprise_slug", string(entry.Owner.Enterprise.Slug)); err != nil { | ||
| return nil, err | ||
| } | ||
| if err := d.Set("ip", string(entry.AllowListValue)); err != nil { | ||
| return nil, err | ||
| } | ||
| if err := d.Set("name", entry.Name); err != nil { | ||
| return nil, err | ||
| } | ||
| if err := d.Set("is_active", entry.IsActive); err != nil { | ||
| return nil, err | ||
| } | ||
| if err := d.Set("created_at", entry.CreatedAt); err != nil { | ||
| return nil, err | ||
| } | ||
| if err := d.Set("updated_at", entry.UpdatedAt); err != nil { | ||
| return nil, err | ||
| } | ||
ErikElkins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| return []*schema.ResourceData{d}, nil | ||
| } | ||
96 changes: 96 additions & 0 deletions
96
github/resource_github_enterprise_ip_allow_list_entry_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| package github | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "strconv" | ||
| "testing" | ||
|
|
||
| "github.com/hashicorp/terraform-plugin-testing/helper/resource" | ||
| ) | ||
|
|
||
| func TestAccGithubEnterpriseIpAllowListEntry(t *testing.T) { | ||
| t.Run("basic", func(t *testing.T) { | ||
| resourceName := "github_enterprise_ip_allow_list_entry.test" | ||
| ip := "192.168.1.0/24" | ||
| name := "Test Entry" | ||
| isActive := true | ||
|
|
||
| config := ` | ||
| resource "github_enterprise_ip_allow_list_entry" "test" { | ||
| enterprise_slug = "%s" | ||
| ip = "%s" | ||
| name = "%s" | ||
| is_active = %t | ||
| } | ||
| ` | ||
|
|
||
| resource.Test(t, resource.TestCase{ | ||
| PreCheck: func() { | ||
| skipUnlessEnterprise(t) | ||
| }, | ||
| ProviderFactories: providerFactories, | ||
| Steps: []resource.TestStep{ | ||
| { | ||
| Config: fmt.Sprintf(config, testAccConf.enterpriseSlug, ip, name, isActive), | ||
| Check: resource.ComposeTestCheckFunc( | ||
| resource.TestCheckResourceAttr(resourceName, "enterprise_slug", testAccConf.enterpriseSlug), | ||
| resource.TestCheckResourceAttr(resourceName, "ip", ip), | ||
| resource.TestCheckResourceAttr(resourceName, "name", name), | ||
| resource.TestCheckResourceAttr(resourceName, "is_active", strconv.FormatBool(isActive)), | ||
| ), | ||
| }, | ||
| { | ||
| ResourceName: resourceName, | ||
| ImportState: true, | ||
| ImportStateVerify: true, | ||
| }, | ||
| }, | ||
| }) | ||
| }) | ||
| t.Run("update", func(t *testing.T) { | ||
| resourceName := "github_enterprise_ip_allow_list_entry.test" | ||
| ip := "192.168.1.0/24" | ||
| name := "Test Entry" | ||
| isActive := true | ||
|
|
||
| updatedIP := "10.0.0.0/16" | ||
| updatedName := "Updated Entry" | ||
| updatedIsActive := false | ||
|
|
||
| config := ` | ||
| resource "github_enterprise_ip_allow_list_entry" "test" { | ||
| enterprise_slug = "%s" | ||
| ip = "%s" | ||
| name = "%s" | ||
| is_active = %t | ||
| } | ||
| ` | ||
|
|
||
| resource.Test(t, resource.TestCase{ | ||
| PreCheck: func() { | ||
| skipUnlessEnterprise(t) | ||
| }, | ||
| ProviderFactories: providerFactories, | ||
| Steps: []resource.TestStep{ | ||
| { | ||
| Config: fmt.Sprintf(config, testAccConf.enterpriseSlug, ip, name, isActive), | ||
| Check: resource.ComposeTestCheckFunc( | ||
| resource.TestCheckResourceAttr(resourceName, "enterprise_slug", testAccConf.enterpriseSlug), | ||
| resource.TestCheckResourceAttr(resourceName, "ip", ip), | ||
| resource.TestCheckResourceAttr(resourceName, "name", name), | ||
| resource.TestCheckResourceAttr(resourceName, "is_active", fmt.Sprintf("%t", isActive)), | ||
| ), | ||
| }, | ||
| { | ||
| Config: fmt.Sprintf(config, testAccConf.enterpriseSlug, updatedIP, updatedName, updatedIsActive), | ||
| Check: resource.ComposeTestCheckFunc( | ||
| resource.TestCheckResourceAttr(resourceName, "enterprise_slug", testAccConf.enterpriseSlug), | ||
| resource.TestCheckResourceAttr(resourceName, "ip", updatedIP), | ||
| resource.TestCheckResourceAttr(resourceName, "name", updatedName), | ||
| resource.TestCheckResourceAttr(resourceName, "is_active", fmt.Sprintf("%t", updatedIsActive)), | ||
| ), | ||
| }, | ||
| }, | ||
| }) | ||
| }) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.