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

feat: add vultr container registry resource #445

Merged
merged 7 commits into from
Jun 3, 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
1 change: 1 addition & 0 deletions example/V2Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The v2 Vultr Terraform plugin is backed by our new [V2 API](https://www.vultr.co
- Startup Scripts
- SSH Keys
- Firewall Groups
- Container Registry

#### 2. Newly created resources will return a uuid and you must use uuids to interact with the v2 plugin
- Data Sources, when filtered by ID or any other resource ID, must use the uuid of the resource
Expand Down
11 changes: 9 additions & 2 deletions example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ resource "vultr_firewall_rule" "tcp" {
}

resource "vultr_dns_domain" "my_domain" {
domain = "tf-domain.com"
ip = vultr_instance.my_instance.main_ip
domain = "tf-domain.com"
ip = vultr_instance.my_instance.main_ip
}

resource "vultr_dns_record" "a-record" {
Expand Down Expand Up @@ -78,3 +78,10 @@ resource "vultr_load_balancer" "lb" {
}

}

resource "vultr_container_registry" "vcr1" {
name = "im6hvcr1"
region = "sjc"
plan = "start_up"
public = false
}
2 changes: 1 addition & 1 deletion example/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ output "ip" {

output "fwg_id" {
value = vultr_firewall_group.fwg.id
}
}
1 change: 1 addition & 0 deletions vultr/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func Provider() *schema.Provider {
"vultr_user": resourceVultrUsers(),
"vultr_vpc": resourceVultrVPC(),
"vultr_vpc2": resourceVultrVPC2(),
"vultr_container_registry": resourceVultrContainerRegistry(),
},

ConfigureFunc: providerConfigure,
Expand Down
181 changes: 181 additions & 0 deletions vultr/resource_vultr_container_registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
package vultr

import (
"context"
"fmt"
"log"
"strconv"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/vultr/govultr/v3"
)

func resourceVultrContainerRegistry() *schema.Resource {
return &schema.Resource{
CreateContext: resourceVultrContainerRegistryCreate,
ReadContext: resourceVultrContainerRegistryRead,
UpdateContext: resourceVultrContainerRegistryUpdate,
DeleteContext: resourceVultrContainerRegistryDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},
"plan": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"start_up", "business", "premium", "enterprise"}, false),
},
"region": {
Type: schema.TypeString,
Required: true,
},
"public": {
Type: schema.TypeBool,
Required: true,
},
"urn": {
Type: schema.TypeString,
Computed: true,
Optional: false,
},
"storage": {
Type: schema.TypeMap,
Computed: true,
Optional: false,
},
"root_user": {
Type: schema.TypeMap,
Computed: true,
Optional: false,
},
"date_created": {
Type: schema.TypeString,
Computed: true,
Optional: false,
},
},
}
}

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

crReq := &govultr.ContainerRegistryReq{
Name: strings.ToLower(d.Get("name").(string)),
Region: d.Get("region").(string),
Public: d.Get("public").(bool),
Plan: d.Get("plan").(string),
}

cr, _, err := client.ContainerRegistry.Create(ctx, crReq)
if err != nil {
return diag.Errorf("error creating container registry: %v", err)
}

d.SetId(cr.ID)
log.Printf("[INFO] Container Registry ID: %s", d.Id())

return resourceVultrContainerRegistryRead(ctx, d, meta)
}

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

cr, _, err := client.ContainerRegistry.Get(ctx, d.Id())
if err != nil {
if strings.Contains(err.Error(), "Invalid container registry ID") {
log.Printf("[WARN] Vultr container registry (%s) not found", d.Id())
d.SetId("")
return nil
}
return diag.Errorf("error getting container registry: %v", err)
}

if err := d.Set("name", cr.Name); err != nil {
return diag.Errorf("unable to set resource container registry `name` read value: %v", err)
}
if err := d.Set("urn", cr.URN); err != nil {
return diag.Errorf("unable to set resource container registry `urn` read value: %v", err)
}
if err := d.Set("storage", flattenCRStorage(cr)); err != nil {
return diag.Errorf("unable to set resource container registry `storage` read value: %v", err)
}
if err := d.Set("root_user", flattenCRRootUser(cr)); err != nil {
return diag.Errorf("unable to set resource container registry `root_user` read value: %v", err)
}
if err := d.Set("public", cr.Public); err != nil {
return diag.Errorf("unable to set resource container `public` read value: %v", err)
}
if err := d.Set("date_created", cr.DateCreated); err != nil {
return diag.Errorf("unable to set resource container `date_created` read value: %v", err)
}

return nil
}

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

vcr := &govultr.ContainerRegistryUpdateReq{}

if d.HasChange("plan") {
vcr.Plan = govultr.StringToStringPtr(d.Get("plan").(string))
}

if d.HasChange("public") {
vcr.Public = govultr.BoolToBoolPtr(d.Get("public").(bool))
}

log.Printf("[INFO] Updating container registry: %s", d.Id())

cr, _, err := client.ContainerRegistry.Update(ctx, d.Id(), vcr)
if err != nil {
return diag.Errorf("error updating container registry: %v", err)
}

d.SetId(cr.ID)
log.Printf("[INFO] Container Registry ID: %s", d.Id())

return resourceVultrContainerRegistryRead(ctx, d, meta)
}

func resourceVultrContainerRegistryDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*Client).govultrClient()
log.Printf("[INFO] Deleting container: %s", d.Id())

err := client.ContainerRegistry.Delete(ctx, d.Id())

if err != nil {
return diag.Errorf("error destroying Container Registry (%s): %v", d.Id(), err)
}

return nil
}

func flattenCRStorage(cr *govultr.ContainerRegistry) map[string]interface{} {
f := map[string]interface{}{
"allowed": fmt.Sprintf("%.2f GB", cr.Storage.Allowed.GigaBytes),
"used": fmt.Sprintf("%.2f GB", cr.Storage.Used.GigaBytes),
}
return f
}

func flattenCRRootUser(cr *govultr.ContainerRegistry) map[string]interface{} {
f := map[string]interface{}{
"id": strconv.Itoa(cr.RootUser.ID),
"username": cr.RootUser.UserName,
"password": cr.RootUser.Password,
"root": strconv.FormatBool(cr.RootUser.Root),
"date_created": cr.RootUser.DateCreated,
"date_modified": cr.RootUser.DateModified,
}
return f
}
60 changes: 60 additions & 0 deletions vultr/resource_vultr_container_registry_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package vultr

import (
"context"
"fmt"
"testing"

"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"
)

func TestAccVultrContainerRegistry(t *testing.T) {
crName := acctest.RandomWithPrefix("tf-cr-cr")
optik-aper marked this conversation as resolved.
Show resolved Hide resolved

name := "vultr_container_registry.foo"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
CheckDestroy: testAccCheckVultrContainerRegistryDestroy,
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccVultrContainerRegistryBase(crName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(name, "name", crName),
resource.TestCheckResourceAttrSet(name, "plan"),
resource.TestCheckResourceAttrSet(name, "region"),
resource.TestCheckResourceAttrSet(name, "public"),
),
},
},
})
}

func testAccCheckVultrContainerRegistryDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "vultr_container_registry" {
continue
}

crID := rs.Primary.ID
client := testAccProvider.Meta().(*Client).govultrClient()

_, _, err := client.ContainerRegistry.Get(context.Background(), crID)
if err == nil {
return fmt.Errorf("vpc still exists: %s", crID)
}
}
return nil
}

func testAccVultrContainerRegistryBase(name string) string {
return fmt.Sprintf(`
resource "vultr_container_registry" "foo" {
name = "%s"
region = "alt"
public = true
plan = "start_up"
} `, name)
}
Loading