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

Add ns meta and capabilities #287

Merged
merged 5 commits into from
Sep 19, 2022
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
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
## 1.4.18 (Unreleased)
## 1.4.19 (Unreleased)

IMPROVEMENTS:
* resources/nomad_namespace: add support for `meta` and `capabilities` ([#287](https://github.com/hashicorp/terraform-provider-nomad/pull/287))
* data source/nomad_namespace: add support for `meta` and `capabilities` ([#287](https://github.com/hashicorp/terraform-provider-nomad/pull/287))

## 1.4.18 (August 31, 2022)

* **Target Nomad 1.3.4**: updated the nomad client to support Nomad API and jobspec version 1.3.4 ([#282](https://github.com/hashicorp/terraform-provider-nomad/pull/282))

Expand Down
18 changes: 18 additions & 0 deletions nomad/data_source_namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ func dataSourceNamespace() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"meta": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"capabilities": {
Type: schema.TypeSet,
Computed: true,
Elem: resourceNamespaceCapabilities(),
},
},
}
}
Expand All @@ -42,6 +54,12 @@ func namespaceDataSourceRead(d *schema.ResourceData, meta interface{}) error {
if err = d.Set("quota", ns.Quota); err != nil {
return fmt.Errorf("Failed to set 'quota': %v", err)
}
if err = d.Set("meta", ns.Meta); err != nil {
return fmt.Errorf("Failed to set 'meta': %v", err)
}
if err = d.Set("capabilities", flattenNamespaceCapabilities(ns.Capabilities)); err != nil {
return fmt.Errorf("Failed to set 'capabilities': %v", err)
}

d.SetId(client.Address() + "/namespace/" + name)
return nil
Expand Down
42 changes: 40 additions & 2 deletions nomad/data_source_namespace_test.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package nomad

import (
"fmt"
"regexp"
"testing"

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

func TestDataSourceNamespace(t *testing.T) {
resourceName := "data.nomad_namespace.test"
name := acctest.RandomWithPrefix("tf-nomad-test")

resource.Test(t, resource.TestCase{
Providers: testProviders,
PreCheck: func() { testAccPreCheck(t); testCheckEnt(t) },
Steps: []resource.TestStep{
{
Config: testDataSourceNamespaceConfig,
Config: testDataSourceDefaultNamespaceConfig,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "default"),
resource.TestCheckResourceAttr(resourceName, "description", "Default shared namespace"),
Expand All @@ -26,11 +29,24 @@ func TestDataSourceNamespace(t *testing.T) {
Config: testDataSourceNamespaceConfig_doesNotExists,
ExpectError: regexp.MustCompile("Namespace not found"),
},
{
Config: testDataSourceNamespace_basicConfig(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", name),
resource.TestCheckResourceAttr(resourceName, "description", "A Terraform acctest namespace"),
resource.TestCheckResourceAttr(resourceName, "quota", ""),
resource.TestCheckResourceAttr(resourceName, "meta.key", "value"),
resource.TestCheckResourceAttr(resourceName, "capabilities.#", "1"),
resource.TestCheckResourceAttr(resourceName, "capabilities.795649181.disabled_task_drivers.0", "raw_exec"),
resource.TestCheckResourceAttr(resourceName, "capabilities.795649181.enabled_task_drivers.0", "docker"),
resource.TestCheckResourceAttr(resourceName, "capabilities.795649181.enabled_task_drivers.1", "exec"),
),
},
},
})
}

const testDataSourceNamespaceConfig = `
const testDataSourceDefaultNamespaceConfig = `
data "nomad_namespace" "test" {
name = "default"
}
Expand All @@ -41,3 +57,25 @@ data "nomad_namespace" "test" {
name = "does-not-exists"
}
`

func testDataSourceNamespace_basicConfig(name string) string {
return fmt.Sprintf(`
resource "nomad_namespace" "test" {
name = "%s"
description = "A Terraform acctest namespace"

meta = {
key = "value",
}

capabilities {
enabled_task_drivers = ["docker", "exec"]
disabled_task_drivers = ["raw_exec"]
}
}

data "nomad_namespace" "test" {
name = nomad_namespace.test.name
}
`, name)
}
120 changes: 115 additions & 5 deletions nomad/resource_namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,69 @@ func resourceNamespace() *schema.Resource {
Optional: true,
Type: schema.TypeString,
},

"meta": {
Description: "Metadata associated with the namespace.",
Optional: true,
Type: schema.TypeMap,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},

"capabilities": {
Description: "Capabilities of the namespace.",
Optional: true,
Type: schema.TypeSet,
Elem: resourceNamespaceCapabilities(),
MaxItems: 1,
},
},
}
}

func resourceNamespaceCapabilities() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"enabled_task_drivers": {
Description: "Enabled task drivers for the namespace.",
Optional: true,
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
},
"disabled_task_drivers": {
Description: "Disabled task drivers for the namespace.",
Optional: true,
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}

func resourceNamespaceWrite(d *schema.ResourceData, meta interface{}) error {
client := meta.(ProviderConfig).client

m := make(map[string]string)
for name, value := range d.Get("meta").(map[string]interface{}) {
m[name] = value.(string)
}

capabilities, err := expandNamespaceCapabilities(d)
if err != nil {
return err
}

namespace := api.Namespace{
Name: d.Get("name").(string),
Description: d.Get("description").(string),
Quota: d.Get("quota").(string),
Name: d.Get("name").(string),
Description: d.Get("description").(string),
Quota: d.Get("quota").(string),
Meta: m,
Capabilities: capabilities,
}

log.Printf("[DEBUG] Upserting namespace %q", namespace.Name)
_, err := client.Namespaces().Register(&namespace, nil)
if err != nil {
if _, err := client.Namespaces().Register(&namespace, nil); err != nil {
return fmt.Errorf("error inserting namespace %q: %s", namespace.Name, err.Error())
}
log.Printf("[DEBUG] Created namespace %q", namespace.Name)
Expand Down Expand Up @@ -121,6 +168,8 @@ func resourceNamespaceRead(d *schema.ResourceData, meta interface{}) error {
d.Set("name", namespace.Name)
d.Set("description", namespace.Description)
d.Set("quota", namespace.Quota)
d.Set("meta", namespace.Meta)
d.Set("capabilities", flattenNamespaceCapabilities(namespace.Capabilities))

return nil
}
Expand Down Expand Up @@ -150,3 +199,64 @@ func resourceNamespaceExists(d *schema.ResourceData, meta interface{}) (bool, er

return true, nil
}

func flattenNamespaceCapabilities(capabilities *api.NamespaceCapabilities) *schema.Set {
if capabilities == nil {
return nil
}
rawCapabilities := map[string]interface{}{}
if capabilities.EnabledTaskDrivers != nil {
enabledI := make([]interface{}, len(capabilities.EnabledTaskDrivers))
for i, v := range capabilities.EnabledTaskDrivers {
enabledI[i] = v
}
rawCapabilities["enabled_task_drivers"] = enabledI
}
if capabilities.DisabledTaskDrivers != nil {
disabledI := make([]interface{}, len(capabilities.DisabledTaskDrivers))
for i, v := range capabilities.DisabledTaskDrivers {
disabledI[i] = v
}
rawCapabilities["disabled_task_drivers"] = disabledI
}

result := []interface{}{rawCapabilities}
return schema.NewSet(schema.HashResource(resourceNamespaceCapabilities()), result)
}

func expandNamespaceCapabilities(d *schema.ResourceData) (*api.NamespaceCapabilities, error) {
capabilitiesI := d.Get("capabilities").(*schema.Set).List()
if len(capabilitiesI) < 1 {
return nil, nil
}
capabilities, ok := capabilitiesI[0].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("expected map[string]interface{} for region capabilities, got %T", capabilitiesI[0])
}
var res api.NamespaceCapabilities
if enaI, ok := capabilities["enabled_task_drivers"]; ok {
enaS, ok := enaI.([]interface{})
if !ok {
return nil, fmt.Errorf("expected enabled_task_drivers to be []string, got %T", enaS)
}
res.EnabledTaskDrivers = make([]string, len(enaS))
for index, value := range enaS {
if val, ok := value.(string); ok {
res.EnabledTaskDrivers[index] = val
}
}
}
if disI, ok := capabilities["disabled_task_drivers"]; ok {
disS, ok := disI.([]interface{})
if !ok {
return nil, fmt.Errorf("expected disabled_task_drivers to be []string, got %T", disS)
}
res.DisabledTaskDrivers = make([]string, len(disS))
for index, value := range disS {
if val, ok := value.(string); ok {
res.DisabledTaskDrivers[index] = val
}
}
}
return &res, nil
}
25 changes: 25 additions & 0 deletions nomad/resource_namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/hashicorp/nomad/api"
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
Expand Down Expand Up @@ -130,6 +131,15 @@ func testResourceNamespace_initialConfig(name string) string {
resource "nomad_namespace" "test" {
name = "%s"
description = "A Terraform acctest namespace"

meta = {
key = "value",
}

capabilities {
enabled_task_drivers = ["docker", "exec"]
disabled_task_drivers = ["raw_exec"]
}
}
`, name)
}
Expand Down Expand Up @@ -174,6 +184,21 @@ func testResourceNamespace_initialCheck(name string) resource.TestCheckFunc {
return fmt.Errorf("expected description to be %q, is %q in API", description, namespace.Description)
}

expectedMeta := map[string]string{
"key": "value",
}
if diff := cmp.Diff(namespace.Meta, expectedMeta); diff != "" {
return fmt.Errorf("namespace meta mismatch (-want +got):\n%s", diff)
}

expectedCapabilities := &api.NamespaceCapabilities{
EnabledTaskDrivers: []string{"docker", "exec"},
DisabledTaskDrivers: []string{"raw_exec"},
}
if diff := cmp.Diff(namespace.Capabilities, expectedCapabilities); diff != "" {
return fmt.Errorf("namespace capabilities mismatch (-want +got):\n%s", diff)
}

return nil
}
}
Expand Down
8 changes: 6 additions & 2 deletions website/docs/d/namespace.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@ data "nomad_namespace" "namespaces" {

The following attributes are exported:

- `description` `(string)` - The description of the namespace.
- `quota` `(string)` - The quota associated with the namespace.
* `description` `(string)` - The description of the namespace.
* `quota` `(string)` - The quota associated with the namespace.
* `meta` `(map[string]string)` - Arbitrary KV metadata associated with the namespace.
* `capabilities` `(block)` - Capabilities of the namespace
* `enabled_task_drivers` `([]string)` - Task drivers enabled for the namespace.
* `disabled_task_drivers` `([]string)` - Task drivers disabled for the namespace.
16 changes: 16 additions & 0 deletions website/docs/r/namespace.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ resource "nomad_namespace" "dev" {
name = "dev"
description = "Shared development environment."
quota = "dev"
meta = {
owner = "John Doe"
foo = "bar"
}
}
```

Expand Down Expand Up @@ -58,3 +62,15 @@ The following arguments are supported:
- `name` `(string: <required>)` - A unique name for the namespace.
- `description` `(string: "")` - A description of the namespace.
- `quota` `(string: "")` - A resource quota to attach to the namespace.
- `meta` `(map[string]string: <optional>)` - Specifies arbitrary KV metadata to associate with the namespace.
- `capabilities` `(block: <optional>)` - A block of capabilities for the namespace. Can't
be repeated. See below for the structure of this block.


### `capabilities` blocks

The `capabilities` block describes the capabilities of the namespace. It supports
the following arguments:

- `enabled_task_drivers` `([]string: <optional>)` - Task drivers enabled for the namespace.
- `disabled_task_drivers` `([]string: <optional>)` - Task drivers disabled for the namespace.