Skip to content
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

Create devops instance #135

Merged
merged 3 commits into from
Jul 22, 2024
Merged
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
73 changes: 73 additions & 0 deletions docs/resources/devops_instance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
page_title: "NIFCLOUD: nifcloud_devops_instance"
subcategory: "DevOps with GitLab"
description: |-
Provides a DevOps instance resource.
---

# nifcloud_devops_instance

Provides a DevOps instance resource.

## Example Usage

```hcl
terraform {
required_providers {
nifcloud = {
source = "nifcloud/nifcloud"
}
}
}

provider "nifcloud" {
region = "jp-east-1"
}

resource "nifcloud_devops_instance" "example" {
instance_id = "example"
instance_type = "c-large"
firewall_group_name = nifcloud_devops_firewall_group.example.name
parameter_group_name = nifcloud_devops_parameter_group.example.name
disk_size = 100
availability_zone = "east-11"
initial_root_password = "initialroo00ootpassword"
}
```

## Argument Reference

The following arguments are supported:

* `availability_zone` - (Optional) The availability zone for the DevOps instance.
* `container_registry_bucket_name` - (Optional) The name of the bucket to put container registry objects.
* `description` - (Optional) Description of the DevOps instance.
* `disk_size` - (Required) The allocated storage in gigabytes.
* `firewall_group_name` - (Required) The name of the DevOps firewall group to associate.
* `initial_root_password` - (Required) Initial password for the root user.
* `instance_id` - (Required) The name of the DevOps instance.
* `instance_type` - (Required) The instance type of the DevOps instance.
* `lfs_bucket_name` - (Optional) The name of the bucket to put LFS objects.
* `network_id` - (Optional, but required if `private_address` is provided) The ID of private lan.
* `object_storage_account` - (Optional, but required if `object_storage_region` is provided) The account name of the object storage service.
* `object_storage_region` - (Optional, but required if `object_storage_account` is provided) The region where the bucket exists.
* `packages_bucket_name` - (Optional) The name of the bucket to put packages.
* `parameter_group_name` - (Required) The name of the DevOps parameter group to associate.
* `private_address` - (Optional, but required if `network_id` is provided) Private IP address for the DevOps instance.
* `to` - (Optional) Mail address where alerts are sent.

## Attribute Reference

In addition to the arguments listed above, the following computed attributes are exported:

* `gitlab_url` - URL for GitLab.
* `registry_url` - URL for GitLab container registry.
* `public_ip_address` - Public IP address for the DevOps instance.

## Import

nifcloud_devops_instance can be imported using the `parameter corresponding to id`, e.g.

```
$ terraform import nifcloud_devops_instance.example foo
```
31 changes: 31 additions & 0 deletions examples/devops_instance/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
terraform {
required_providers {
nifcloud = {
source = "nifcloud/nifcloud"
}
}
}

provider "nifcloud" {
region = "jp-east-1"
}

resource "nifcloud_devops_instance" "example" {
instance_id = "example"
instance_type = "c-large"
firewall_group_name = nifcloud_devops_firewall_group.example.name
parameter_group_name = nifcloud_devops_parameter_group.example.name
disk_size = 100
availability_zone = "east-11"
initial_root_password = "initialroo00ootpassword"
to = "[email protected]"
}

resource "nifcloud_devops_firewall_group" "example" {
name = "example"
availability_zone = "east-11"
}

resource "nifcloud_devops_parameter_group" "example" {
name = "example"
}
6 changes: 3 additions & 3 deletions nifcloud/acc/devops_firewall_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ func init() {
resource.AddTestSweepers("nifcloud_devops_firewall_group", &resource.Sweeper{
Name: "nifcloud_devops_firewall_group",
F: testSweepDevOpsFirewallGroup,
// Dependencies: []string{
// "nifcloud_devops_instance",
// },
Dependencies: []string{
"nifcloud_devops_instance",
},
})
}

Expand Down
274 changes: 274 additions & 0 deletions nifcloud/acc/devops_instance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
package acc

import (
"context"
"errors"
"fmt"
"os"
"strings"
"testing"

"github.com/aws/smithy-go"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/nifcloud/nifcloud-sdk-go/nifcloud"
"github.com/nifcloud/nifcloud-sdk-go/service/devops"
"github.com/nifcloud/nifcloud-sdk-go/service/devops/types"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/client"
"golang.org/x/sync/errgroup"
)

func init() {
resource.AddTestSweepers("nifcloud_devops_instance", &resource.Sweeper{
Name: "nifcloud_devops_instance",
F: testSweepDevOpsInstance,
})
}

func TestAcc_DevOpsInstance(t *testing.T) {
var instance types.Instance

resourceName := "nifcloud_devops_instance.basic"
randName := prefix + acctest.RandString(10)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactory,
CheckDestroy: testAccDevOpsInstanceResourceDestroy,
Steps: []resource.TestStep{
{
Config: testAccDevOpsInstance(t, "testdata/devops_instance.tf", randName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDevOpsInstanceExists(resourceName, &instance),
testAccCheckDevOpsInstanceValues(&instance, randName),
resource.TestCheckResourceAttr(resourceName, "instance_id", randName),
resource.TestCheckResourceAttr(resourceName, "instance_type", "c-large"),
resource.TestCheckResourceAttr(resourceName, "firewall_group_name", randName),
resource.TestCheckResourceAttr(resourceName, "parameter_group_name", randName),
resource.TestCheckResourceAttr(resourceName, "disk_size", "100"),
resource.TestCheckResourceAttr(resourceName, "availability_zone", "east-14"),
resource.TestCheckResourceAttr(resourceName, "description", "tfacc-memo"),
resource.TestCheckResourceAttr(resourceName, "to", "[email protected]"),
resource.TestCheckResourceAttr(resourceName, "gitlab_url", "https://"+randName+".jp-east-1.gitlab.devops.nifcloud.com"),
resource.TestCheckResourceAttr(resourceName, "registry_url", "https://registry-"+randName+".jp-east-1.gitlab.devops.nifcloud.com"),
),
},
{
Config: testAccDevOpsInstance(t, "testdata/devops_instance_update.tf", randName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDevOpsInstanceExists(resourceName, &instance),
testAccCheckDevOpsInstanceValuesUpdated(&instance, randName),
resource.TestCheckResourceAttr(resourceName, "instance_id", randName),
resource.TestCheckResourceAttr(resourceName, "instance_type", "e-large"),
resource.TestCheckResourceAttr(resourceName, "firewall_group_name", randName+"-upd"),
resource.TestCheckResourceAttr(resourceName, "parameter_group_name", randName),
resource.TestCheckResourceAttr(resourceName, "disk_size", "300"),
resource.TestCheckResourceAttr(resourceName, "availability_zone", "east-14"),
resource.TestCheckResourceAttr(resourceName, "description", "tfacc-memo-upd"),
resource.TestCheckResourceAttr(resourceName, "to", "[email protected]"),
resource.TestCheckResourceAttr(resourceName, "gitlab_url", "https://"+randName+".jp-east-1.gitlab.devops.nifcloud.com"),
resource.TestCheckResourceAttr(resourceName, "registry_url", "https://registry-"+randName+".jp-east-1.gitlab.devops.nifcloud.com"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"initial_root_password",
},
},
},
})
}

func testAccDevOpsInstance(t *testing.T, fileName, rName string) string {
b, err := os.ReadFile(fileName)
if err != nil {
t.Fatal(err)
}
return fmt.Sprintf(string(b), rName, rName, rName, rName)
}

func testAccCheckDevOpsInstanceExists(n string, instance *types.Instance) resource.TestCheckFunc {
return func(s *terraform.State) error {
saved, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("no devops instance resource: %s", n)
}

if saved.Primary.ID == "" {
return fmt.Errorf("no devops instance id is set")
}

svc := testAccProvider.Meta().(*client.Client).DevOps
res, err := svc.GetInstance(context.Background(), &devops.GetInstanceInput{
InstanceId: nifcloud.String(saved.Primary.ID),
})
if err != nil {
return err
}

if res.Instance == nil {
return fmt.Errorf("devops instance is not found in cloud: %s", saved.Primary.ID)
}

if nifcloud.ToString(res.Instance.InstanceId) != saved.Primary.ID {
return fmt.Errorf("devops instance is not found in cloud: %s", saved.Primary.ID)
}

*instance = *res.Instance

return nil
}
}

func testAccCheckDevOpsInstanceValues(instance *types.Instance, rName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if nifcloud.ToString(instance.InstanceId) != rName {
return fmt.Errorf("bad instance id state, expected \"%s\", got: %#v", rName, nifcloud.ToString(instance.InstanceId))
}

if nifcloud.ToString(instance.InstanceType) != "c-large" {
return fmt.Errorf("bad instance_type state, expected \"c-large\", got: %#v", nifcloud.ToString(instance.InstanceType))
}

if nifcloud.ToString(instance.FirewallGroupName) != rName {
return fmt.Errorf("bad firewall_group_name state, expected \"%s\", got: %#v", rName, nifcloud.ToString(instance.FirewallGroupName))
}

if nifcloud.ToString(instance.ParameterGroupName) != rName {
return fmt.Errorf("bad parameter_group_name state, expected \"%s\", got: %#v", rName, nifcloud.ToString(instance.ParameterGroupName))
}

if nifcloud.ToInt32(instance.DiskSize) != int32(100) {
return fmt.Errorf("bad disk_size state, expected 100, got: %#v", nifcloud.ToInt32(instance.DiskSize))
}

if nifcloud.ToString(instance.AvailabilityZone) != "east-14" {
return fmt.Errorf("bad availability_zone state, expected \"east-14\", got: %#v", nifcloud.ToString(instance.AvailabilityZone))
}

if nifcloud.ToString(instance.Description) != "tfacc-memo" {
return fmt.Errorf("bad description state, expected \"tfacc-memo\", got: %#v", nifcloud.ToString(instance.Description))
}

if nifcloud.ToString(instance.To) != "[email protected]" {
return fmt.Errorf("bad to state, expected \"[email protected]\", got: %#v", nifcloud.ToString(instance.To))
}

if nifcloud.ToString(instance.GitlabUrl) != "https://"+rName+".jp-east-1.gitlab.devops.nifcloud.com" {
return fmt.Errorf("bad gitlab_url state, expected \"https://%s.jp-east-1.gitlab.devops.nifcloud.com\", got: %#v", rName, nifcloud.ToString(instance.GitlabUrl))
}

if nifcloud.ToString(instance.RegistryUrl) != "https://registry-"+rName+".jp-east-1.gitlab.devops.nifcloud.com" {
return fmt.Errorf("bad registry_url state, expected \"https://registry-%s.jp-east-1.gitlab.devops.nifcloud.com\", got: %#v", rName, nifcloud.ToString(instance.RegistryUrl))
}

return nil
}
}

func testAccCheckDevOpsInstanceValuesUpdated(instance *types.Instance, rName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if nifcloud.ToString(instance.InstanceId) != rName {
return fmt.Errorf("bad instance id state, expected \"%s\", got: %#v", rName, nifcloud.ToString(instance.InstanceId))
}

if nifcloud.ToString(instance.InstanceType) != "e-large" {
return fmt.Errorf("bad instance_type state, expected \"e-large\", got: %#v", nifcloud.ToString(instance.InstanceType))
}

if nifcloud.ToString(instance.FirewallGroupName) != rName+"-upd" {
return fmt.Errorf("bad firewall_group_name state, expected \"%s\", got: %#v", rName+"-upd", nifcloud.ToString(instance.FirewallGroupName))
}

if nifcloud.ToString(instance.ParameterGroupName) != rName {
return fmt.Errorf("bad parameter_group_name state, expected \"%s\", got: %#v", rName, nifcloud.ToString(instance.ParameterGroupName))
}

if nifcloud.ToInt32(instance.DiskSize) != int32(300) {
return fmt.Errorf("bad disk_size state, expected 300, got: %#v", nifcloud.ToInt32(instance.DiskSize))
}

if nifcloud.ToString(instance.AvailabilityZone) != "east-14" {
return fmt.Errorf("bad availability_zone state, expected \"east-14\", got: %#v", nifcloud.ToString(instance.AvailabilityZone))
}

if nifcloud.ToString(instance.Description) != "tfacc-memo-upd" {
return fmt.Errorf("bad description state, expected \"tfacc-memo-upd\", got: %#v", nifcloud.ToString(instance.Description))
}

if nifcloud.ToString(instance.To) != "[email protected]" {
return fmt.Errorf("bad to state, expected \"[email protected]\", got: %#v", nifcloud.ToString(instance.To))
}

if nifcloud.ToString(instance.GitlabUrl) != "https://"+rName+".jp-east-1.gitlab.devops.nifcloud.com" {
return fmt.Errorf("bad gitlab_url state, expected \"https://%s.jp-east-1.gitlab.devops.nifcloud.com\", got: %#v", rName, nifcloud.ToString(instance.GitlabUrl))
}

if nifcloud.ToString(instance.RegistryUrl) != "https://registry-"+rName+".jp-east-1.gitlab.devops.nifcloud.com" {
return fmt.Errorf("bad registry_url state, expected \"https://registry-%s.jp-east-1.gitlab.devops.nifcloud.com\", got: %#v", rName, nifcloud.ToString(instance.RegistryUrl))
}

return nil
}
}

func testAccDevOpsInstanceResourceDestroy(s *terraform.State) error {
svc := testAccProvider.Meta().(*client.Client).DevOps

for _, rs := range s.RootModule().Resources {
if rs.Type != "nifcloud_devops_instance" {
continue
}

_, err := svc.GetInstance(context.Background(), &devops.GetInstanceInput{
InstanceId: nifcloud.String(rs.Primary.ID),
})

if err != nil {
var awsErr smithy.APIError
if errors.As(err, &awsErr) && awsErr.ErrorCode() == "Client.InvalidParameterNotFound.Instance" {
return nil
}
return fmt.Errorf("failed GetInstance: %s", err)
}

return fmt.Errorf("devops instance (%s) still exists", rs.Primary.ID)
}
return nil
}

func testSweepDevOpsInstance(region string) error {
ctx := context.Background()
svc := sharedClientForRegion(region).DevOps

res, err := svc.ListInstances(ctx, nil)
if err != nil {
return err
}

var sweepInstances []string
for _, i := range res.Instances {
if strings.HasPrefix(nifcloud.ToString(i.InstanceId), prefix) {
sweepInstances = append(sweepInstances, nifcloud.ToString(i.InstanceId))
}
}

eg, ctx := errgroup.WithContext(ctx)
for _, n := range sweepInstances {
instance := n
eg.Go(func() error {
_, err := svc.DeleteInstance(ctx, &devops.DeleteInstanceInput{
InstanceId: nifcloud.String(instance),
})
return err
})
}
if err := eg.Wait(); err != nil {
return err
}
return nil
}
Loading
Loading