Skip to content

Adding github_organization_ip_allow_list_entry resource #2650

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
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ func Provider() *schema.Provider {
"github_membership": resourceGithubMembership(),
"github_organization_block": resourceOrganizationBlock(),
"github_organization_custom_role": resourceGithubOrganizationCustomRole(),
"github_organization_ip_allow_list_entry": resourceGithubOrganizationIpAllowListEntry(),
"github_organization_project": resourceGithubOrganizationProject(),
"github_organization_security_manager": resourceGithubOrganizationSecurityManager(),
"github_organization_ruleset": resourceGithubOrganizationRuleset(),
Expand Down
197 changes: 197 additions & 0 deletions github/resource_github_organization_ip_allow_list_entry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
package github

import (
"context"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/shurcooL/githubv4"
)

func resourceGithubOrganizationIpAllowListEntry() *schema.Resource {
return &schema.Resource{
Create: resourceGithubOrganizationIpAllowListEntryCreate,
Read: resourceGithubOrganizationIpAllowListEntryRead,
Update: resourceGithubOrganizationIpAllowListEntryUpdate,
Delete: resourceGithubOrganizationIpAllowListEntryDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"ip": {
Type: schema.TypeString,
Required: true,
Description: "An IP address or range of IP addresses in CIDR notation.",
},
"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.",
},
},
}
}

func resourceGithubOrganizationIpAllowListEntryCreate(d *schema.ResourceData, meta interface{}) error {
err := checkOrganization(meta)
if err != nil {
return err
}

client := meta.(*Owner).v4client
orgName := meta.(*Owner).name
ctx := context.WithValue(context.Background(), ctxId, d.Id())

// First, get the organization ID as we need it for the mutation
var getOrgQuery struct {
Organization struct {
ID githubv4.ID
} `graphql:"organization(login: $login)"`
}

variables := map[string]interface{}{
"login": githubv4.String(orgName),
}

err = client.Query(ctx, &getOrgQuery, variables)
if err != nil {
return 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
}
} `graphql:"createIpAllowListEntry(input: $input)"`
}

name := d.Get("name").(string)
input := githubv4.CreateIpAllowListEntryInput{
OwnerID: getOrgQuery.Organization.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 err
}

d.SetId(string(mutation.CreateIpAllowListEntry.IpAllowListEntry.ID))

return resourceGithubOrganizationIpAllowListEntryRead(d, meta)
}

func resourceGithubOrganizationIpAllowListEntryRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v4client
ctx := context.WithValue(context.Background(), ctxId, d.Id())

var query struct {
Node struct {
IpAllowListEntry struct {
ID githubv4.String
AllowListValue githubv4.String
Name githubv4.String
IsActive githubv4.Boolean
CreatedAt githubv4.String
} `graphql:"... on IpAllowListEntry"`
} `graphql:"node(id: $id)"`
}

variables := map[string]interface{}{
"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") {
log.Printf("[INFO] Removing IP allow list entry (%s) from state because it no longer exists in GitHub", d.Id())
d.SetId("")
return nil
}
return err
}

entry := query.Node.IpAllowListEntry

d.Set("ip", entry.AllowListValue)
d.Set("name", entry.Name)
d.Set("is_active", entry.IsActive)

return nil
}

func resourceGithubOrganizationIpAllowListEntryUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v4client
ctx := context.WithValue(context.Background(), ctxId, d.Id())

var mutation struct {
UpdateIpAllowListEntry struct {
IpAllowListEntry struct {
ID githubv4.String
AllowListValue githubv4.String
Name githubv4.String
IsActive githubv4.Boolean
}
} `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 err
}

return resourceGithubOrganizationIpAllowListEntryRead(d, meta)
}

func resourceGithubOrganizationIpAllowListEntryDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Owner).v4client
ctx := context.WithValue(context.Background(), ctxId, d.Id())

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)
if err != nil {
return err
}

d.SetId("")
return nil
}
99 changes: 99 additions & 0 deletions github/resource_github_organization_ip_allow_list_entry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package github

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccGithubOrganizationIpAllowListEntry_basic(t *testing.T) {
t.Skip("Acceptance test requires a real GitHub organization")

resourceName := "github_organization_ip_allow_list_entry.test"
orgName := "test-organization"
ip := "192.168.1.0/24"
name := "Test Entry"
isActive := true

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheckOrg(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccGithubOrganizationIpAllowListEntryConfig(orgName, ip, name, isActive),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "ip", ip),
resource.TestCheckResourceAttr(resourceName, "name", name),
resource.TestCheckResourceAttr(resourceName, "is_active", fmt.Sprintf("%t", isActive)),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccGithubOrganizationIpAllowListEntry_update(t *testing.T) {
t.Skip("Acceptance test requires a real GitHub organization")

resourceName := "github_organization_ip_allow_list_entry.test"
orgName := "test-organization"
ip := "192.168.1.0/24"
name := "Test Entry"
isActive := true

updatedIP := "10.0.0.0/16"
updatedName := "Updated Entry"
updatedIsActive := false

resource.Test(t, resource.TestCase{
PreCheck: func() {
testAccPreCheckOrg(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccGithubOrganizationIpAllowListEntryConfig(orgName, ip, name, isActive),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "ip", ip),
resource.TestCheckResourceAttr(resourceName, "name", name),
resource.TestCheckResourceAttr(resourceName, "is_active", fmt.Sprintf("%t", isActive)),
),
},
{
Config: testAccGithubOrganizationIpAllowListEntryConfig(orgName, updatedIP, updatedName, updatedIsActive),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "ip", updatedIP),
resource.TestCheckResourceAttr(resourceName, "name", updatedName),
resource.TestCheckResourceAttr(resourceName, "is_active", fmt.Sprintf("%t", updatedIsActive)),
),
},
},
})
}

func testAccGithubOrganizationIpAllowListEntryConfig(orgName, ip, name string, isActive bool) string {
return fmt.Sprintf(`
provider "github" {
owner = "%s"
}

resource "github_organization_ip_allow_list_entry" "test" {
ip = "%s"
name = "%s"
is_active = %t
}
`, orgName, ip, name, isActive)
}

func testAccPreCheckOrg(t *testing.T) {
if v := testAccProvider.Meta().(*Owner).name; v == "" {
t.Fatal("The GITHUB_OWNER environment variable must be set for acceptance tests")
}
}
36 changes: 36 additions & 0 deletions website/docs/r/organization_ip_allow_list_entry.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
layout: "github"
page_title: "GitHub: github_organization_ip_allow_list_entry"
description: |-
Creates and manages IP allow list entries within a GitHub organization
---

# github_organization_ip_allow_list_entry

This resource allows you to create and manage IP allow list entries for a GitHub organization. IP allow list entries define IP addresses or ranges that are permitted to access private resources in the organization.

## Example Usage

```hcl
resource "github_organization_ip_allow_list_entry" "test" {
ip = "192.168.1.0/20"
name = "My IP Range Name"
is_active = true
}
```

## Argument Reference

The following arguments are supported:

* `ip` - (Required) An IP address or range of IP addresses in CIDR notation.
* `name` - (Optional) A descriptive name for the IP allow list entry.
* `is_active` - (Optional) Whether the entry is currently active. Default: true.

## Import

This resource can be imported using the ID of the IP allow list entry:

```bash
$ terraform import github_organization_ip_allow_list_entry.test IALE_kwHOC1234567890a
```
Loading