Skip to content

Commit

Permalink
Merge pull request #138 from nifcloud/feature/devops-runner
Browse files Browse the repository at this point in the history
Create devops runner
  • Loading branch information
tunakyonn authored Jul 25, 2024
2 parents 3455485 + 1163898 commit 0029f72
Show file tree
Hide file tree
Showing 17 changed files with 960 additions and 3 deletions.
49 changes: 49 additions & 0 deletions docs/resources/devops_runner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
page_title: "NIFCLOUD: nifcloud_devops_runner"
subcategory: "DevOps with GitLab"
description: |-
Provides a DevOps Runner resource.
---

# nifcloud_devops_runner

Provides a DevOps Runner resource.

## Example Usage

```hcl
resource "nifcloud_devops_runner" "example" {
name = "example"
instance_type = "c-small"
availability_zone = "east-11"
concurrent = 10
description = "memo"
}
```

## Argument Reference

The following arguments are supported:

* `availability_zone` - (Optional) The availability zone for the DevOps Runner.
* `concurrent` - (Optional) Limits how many jobs can run concurrently, across all registrations.
* `description` - (Optional) Description of the DevOps Runner.
* `instance_type` - (Required) The instance type of the DevOps Runner.
* `name` - (Required) The name of the DevOps Runner.
* `network_id` - (Optional, but required if `private_address` is provided) The ID of private lan.
* `private_address` - (Optional, but required if `network_id` is provided) Private IP address for the DevOps Runner.

## Attribute Reference

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

* `public_ip_address` - Public IP address for the DevOps Runner.
* `system_id` - GitLab Runner system ID.

## Import

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

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

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

resource "nifcloud_devops_runner" "example" {
name = "example"
instance_type = "c-small"
availability_zone = "east-11"
concurrent = 10
description = "memo"
}
221 changes: 221 additions & 0 deletions nifcloud/acc/devops_runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
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/devopsrunner"
"github.com/nifcloud/nifcloud-sdk-go/service/devopsrunner/types"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/client"
"golang.org/x/sync/errgroup"
)

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

func TestAcc_DevOpsRunner(t *testing.T) {
var runner types.Runner

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

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactory,
CheckDestroy: testAccDevOpsRunnerResourceDestroy,
Steps: []resource.TestStep{
{
Config: testAccDevOpsRunner(t, "testdata/devops_runner.tf", randName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDevOpsRunnerExists(resourceName, &runner),
testAccCheckDevOpsRunnerValues(&runner, randName),
resource.TestCheckResourceAttr(resourceName, "name", randName),
resource.TestCheckResourceAttr(resourceName, "instance_type", "c-small"),
resource.TestCheckResourceAttr(resourceName, "availability_zone", "east-14"),
resource.TestCheckResourceAttr(resourceName, "concurrent", "10"),
resource.TestCheckResourceAttr(resourceName, "description", "tfacc-memo"),
),
},
{
Config: testAccDevOpsRunner(t, "testdata/devops_runner_update.tf", randName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDevOpsRunnerExists(resourceName, &runner),
testAccCheckDevOpsRunnerValuesUpdated(&runner, randName),
resource.TestCheckResourceAttr(resourceName, "name", randName+"-upd"),
resource.TestCheckResourceAttr(resourceName, "instance_type", "e-small"),
resource.TestCheckResourceAttr(resourceName, "availability_zone", "east-14"),
resource.TestCheckResourceAttr(resourceName, "concurrent", "50"),
resource.TestCheckResourceAttr(resourceName, "description", "tfacc-memo-upd"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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

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

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

svc := testAccProvider.Meta().(*client.Client).DevOpsRunner
res, err := svc.GetRunner(context.Background(), &devopsrunner.GetRunnerInput{
RunnerName: nifcloud.String(saved.Primary.ID),
})
if err != nil {
return err
}

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

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

*runner = *res.Runner

return nil
}
}

func testAccCheckDevOpsRunnerValues(runner *types.Runner, rName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if nifcloud.ToString(runner.RunnerName) != rName {
return fmt.Errorf("bad runner name state, expected \"%s\", got: %#v", rName, nifcloud.ToString(runner.RunnerName))
}

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

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

if nifcloud.ToInt32(runner.Concurrent) != int32(10) {
return fmt.Errorf("bad concurrent state, expected 10, got: %#v", nifcloud.ToInt32(runner.Concurrent))
}

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

return nil
}
}

func testAccCheckDevOpsRunnerValuesUpdated(runner *types.Runner, rName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if nifcloud.ToString(runner.RunnerName) != rName+"-upd" {
return fmt.Errorf("bad runner name state, expected \"%s\", got: %#v", rName, nifcloud.ToString(runner.RunnerName))
}

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

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

if nifcloud.ToInt32(runner.Concurrent) != int32(50) {
return fmt.Errorf("bad concurrent state, expected 50, got: %#v", nifcloud.ToInt32(runner.Concurrent))
}

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

return nil
}
}

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

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

_, err := svc.GetRunner(context.Background(), &devopsrunner.GetRunnerInput{
RunnerName: nifcloud.String(rs.Primary.ID),
})

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

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

func testSweepDevOpsRunner(region string) error {
ctx := context.Background()
svc := sharedClientForRegion(region).DevOpsRunner

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

var sweepRunners []string
for _, r := range res.Runners {
if strings.HasPrefix(nifcloud.ToString(r.RunnerName), prefix) {
sweepRunners = append(sweepRunners, nifcloud.ToString(r.RunnerName))
}
}

eg, ctx := errgroup.WithContext(ctx)
for _, n := range sweepRunners {
runner := n
eg.Go(func() error {
_, err := svc.DeleteRunner(ctx, &devopsrunner.DeleteRunnerInput{
RunnerName: nifcloud.String(runner),
})
return err
})
}
if err := eg.Wait(); err != nil {
return err
}
return nil
}
11 changes: 11 additions & 0 deletions nifcloud/acc/testdata/devops_runner.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
provider "nifcloud" {
region = "jp-east-1"
}

resource "nifcloud_devops_runner" "basic" {
name = "%s"
instance_type = "c-small"
availability_zone = "east-14"
concurrent = 10
description = "tfacc-memo"
}
11 changes: 11 additions & 0 deletions nifcloud/acc/testdata/devops_runner_update.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
provider "nifcloud" {
region = "jp-east-1"
}

resource "nifcloud_devops_runner" "basic" {
name = "%s-upd"
instance_type = "e-small"
availability_zone = "east-14"
concurrent = 50
description = "tfacc-memo-upd"
}
2 changes: 2 additions & 0 deletions nifcloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/resources/devops/devopsfirewallgroup"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/resources/devops/devopsinstance"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/resources/devops/devopsparametergroup"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/resources/devops/devopsrunner"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/resources/devops/devopsrunnerparametergroup"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/resources/dns/record"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/resources/dns/zone"
Expand Down Expand Up @@ -134,6 +135,7 @@ func Provider() *schema.Provider {
"nifcloud_devops_parameter_group": devopsparametergroup.New(),
"nifcloud_devops_firewall_group": devopsfirewallgroup.New(),
"nifcloud_devops_backup_rule": devopsbackuprule.New(),
"nifcloud_devops_runner": devopsrunner.New(),
"nifcloud_devops_runner_parameter_group": devopsrunnerparametergroup.New(),
},
}
Expand Down
7 changes: 4 additions & 3 deletions nifcloud/resources/devops/devopsinstance/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,10 @@ func newSchema() map[string]*schema.Schema {
Optional: true,
},
"private_address": {
Type: schema.TypeString,
Description: "Private IP address for the DevOps instance.",
Optional: true,
Type: schema.TypeString,
Description: "Private IP address for the DevOps instance.",
Optional: true,
ValidateFunc: validation.IsCIDR,
},
"object_storage_account": {
Type: schema.TypeString,
Expand Down
31 changes: 31 additions & 0 deletions nifcloud/resources/devops/devopsrunner/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package devopsrunner

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/nifcloud/nifcloud-sdk-go/nifcloud"
"github.com/nifcloud/terraform-provider-nifcloud/nifcloud/client"
)

func createRunner(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
svc := meta.(*client.Client).DevOpsRunner

input := expandCreateRunnerInput(d)

res, err := svc.CreateRunner(ctx, input)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to create a DevOps Runner: %s", err))
}

d.SetId(nifcloud.ToString(res.Runner.RunnerName))

err = waitUntilRunnerRunning(ctx, d, svc)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to wait for the DevOps Runner to become ready: %s", err))
}

return updateRunner(ctx, d, meta)
}
Loading

0 comments on commit 0029f72

Please sign in to comment.