From acc9d52703c3d80caa4a1aaf1a82f5cc4eb842d5 Mon Sep 17 00:00:00 2001 From: Lance Haig Date: Thu, 8 Dec 2022 15:49:32 +0100 Subject: [PATCH 1/8] Initial support for adding the ability to ACL bootstrap a cluster with the provider --- nomad/provider.go | 1 + nomad/resource_acl_bootstrap.go | 109 ++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 nomad/resource_acl_bootstrap.go diff --git a/nomad/provider.go b/nomad/provider.go index 5f2c5729..7821b991 100644 --- a/nomad/provider.go +++ b/nomad/provider.go @@ -173,6 +173,7 @@ func Provider() *schema.Provider { ResourcesMap: map[string]*schema.Resource{ "nomad_acl_auth_method": resourceACLAuthMethod(), "nomad_acl_binding_rule": resourceACLBindingRule(), + "nomad_acl_bootstrap": resourceACLBootStrap(), "nomad_acl_policy": resourceACLPolicy(), "nomad_acl_role": resourceACLRole(), "nomad_acl_token": resourceACLToken(), diff --git a/nomad/resource_acl_bootstrap.go b/nomad/resource_acl_bootstrap.go new file mode 100644 index 00000000..1ff1dece --- /dev/null +++ b/nomad/resource_acl_bootstrap.go @@ -0,0 +1,109 @@ +package nomad + +import ( + "fmt" + "log" + "strings" + "time" + + "github.com/hashicorp/nomad/api" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceACLBootStrap() *schema.Resource { + return &schema.Resource{ + Create: resourceACLBootStrapCreate, + Delete: resourceACLBootStrapDelete, + Read: resourceACLBootStrapRead, + Exists: resourceACLBootStrapExists, + + Schema: map[string]*schema.Schema{ + "accessor_id": { + Description: "Nomad-generated ID for this token.", + Computed: true, + Type: schema.TypeString, + }, + "bootstrap_token": { + Description: "The value that grants access to Nomad.", + Computed: true, + Optional: true, + Sensitive: true, + Type: schema.TypeString, + }, + }, + } +} + +func resourceACLBootStrapCreate(d *schema.ResourceData, meta interface{}) error { + providerConfig := meta.(ProviderConfig) + client := providerConfig.client + + token := api.BootstrapRequest{ + BootstrapSecret: d.Get("bootstrap_token").(string), + } + // create our token + log.Println("[DEBUG] Creating ACL Bootstrap token") + resp, _, err := client.ACLTokens().BootstrapOpts(token.BootstrapSecret, nil) + if err != nil { + return fmt.Errorf("error bootstrapping the cluster: %s", err.Error()) + } + log.Printf("[DEBUG] Created ACL token AccessorID %q", resp.AccessorID) + d.SetId(resp.AccessorID) + + return resourceACLBootStrapRead(d, meta) +} + +// not implemented as a cluster bootstrap can't be reverted +func resourceACLBootStrapDelete(d *schema.ResourceData, meta interface{}) error { + return nil +} + +func resourceACLBootStrapRead(d *schema.ResourceData, meta interface{}) error { + providerConfig := meta.(ProviderConfig) + client := providerConfig.client + accessor := d.Id() + + // retrieve the token + log.Printf("[DEBUG] Reading ACL bootstrap token %q", accessor) + token, _, err := client.ACLTokens().Info(accessor, nil) + if err != nil { + // we have Exists, so no need to handle 404 + return fmt.Errorf("error reading ACL token %q: %s", accessor, err.Error()) + } + log.Printf("[DEBUG] Read ACL bootstrap token %q", accessor) + + var expirationTime string + if token.ExpirationTime != nil { + expirationTime = token.ExpirationTime.Format(time.RFC3339) + } + token.SecretID = "00000000-0000-0000-0000-000000000000" + + d.Set("accessor_id", token.AccessorID) + d.Set("secret_id", token.SecretID) + log.Printf("[DEBUG] TOKENID", token.SecretID) + d.Set("create_time", token.CreateTime.UTC().String()) + d.Set("expiration_tll", token.ExpirationTTL.String()) + d.Set("expiration_time", expirationTime) + + return nil +} + +func resourceACLBootStrapExists(d *schema.ResourceData, meta interface{}) (bool, error) { + providerConfig := meta.(ProviderConfig) + client := providerConfig.client + + accessor := d.Id() + log.Printf("[DEBUG] Checking if ACL token %q exists", accessor) + _, _, err := client.ACLTokens().Info(accessor, nil) + if err != nil { + // As of Nomad 0.4.1, the API client returns an error for 404 + // rather than a nil result, so we must check this way. + if strings.Contains(err.Error(), "404") { + return false, nil + } + + return true, fmt.Errorf("error checking for ACL token %q: %#v", accessor, err) + } + + return true, nil +} From 913d3dd25a29e2852f04a1f5718cd9334f5c2f77 Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 15 Sep 2025 10:56:53 +0100 Subject: [PATCH 2/8] Add copyright header and fix function naming in ACL bootstrap resource --- nomad/resource_acl_bootstrap.go | 36 +++++++++++++-------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/nomad/resource_acl_bootstrap.go b/nomad/resource_acl_bootstrap.go index 1ff1dece..a33074b8 100644 --- a/nomad/resource_acl_bootstrap.go +++ b/nomad/resource_acl_bootstrap.go @@ -1,21 +1,23 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package nomad import ( "fmt" "log" "strings" - "time" "github.com/hashicorp/nomad/api" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -func resourceACLBootStrap() *schema.Resource { +func resourceACLBootstrap() *schema.Resource { return &schema.Resource{ - Create: resourceACLBootStrapCreate, - Delete: resourceACLBootStrapDelete, - Read: resourceACLBootStrapRead, - Exists: resourceACLBootStrapExists, + Create: resourceACLBootstrapCreate, + Delete: resourceACLBootstrapDelete, + Read: resourceACLBootstrapRead, + Exists: resourceACLBootstrapExists, Schema: map[string]*schema.Schema{ "accessor_id": { @@ -34,7 +36,7 @@ func resourceACLBootStrap() *schema.Resource { } } -func resourceACLBootStrapCreate(d *schema.ResourceData, meta interface{}) error { +func resourceACLBootstrapCreate(d *schema.ResourceData, meta interface{}) error { providerConfig := meta.(ProviderConfig) client := providerConfig.client @@ -50,15 +52,15 @@ func resourceACLBootStrapCreate(d *schema.ResourceData, meta interface{}) error log.Printf("[DEBUG] Created ACL token AccessorID %q", resp.AccessorID) d.SetId(resp.AccessorID) - return resourceACLBootStrapRead(d, meta) + return resourceACLBootstrapRead(d, meta) } // not implemented as a cluster bootstrap can't be reverted -func resourceACLBootStrapDelete(d *schema.ResourceData, meta interface{}) error { +func resourceACLBootstrapDelete(d *schema.ResourceData, meta interface{}) error { return nil } -func resourceACLBootStrapRead(d *schema.ResourceData, meta interface{}) error { +func resourceACLBootstrapRead(d *schema.ResourceData, meta interface{}) error { providerConfig := meta.(ProviderConfig) client := providerConfig.client accessor := d.Id() @@ -72,23 +74,13 @@ func resourceACLBootStrapRead(d *schema.ResourceData, meta interface{}) error { } log.Printf("[DEBUG] Read ACL bootstrap token %q", accessor) - var expirationTime string - if token.ExpirationTime != nil { - expirationTime = token.ExpirationTime.Format(time.RFC3339) - } - token.SecretID = "00000000-0000-0000-0000-000000000000" - d.Set("accessor_id", token.AccessorID) - d.Set("secret_id", token.SecretID) - log.Printf("[DEBUG] TOKENID", token.SecretID) - d.Set("create_time", token.CreateTime.UTC().String()) - d.Set("expiration_tll", token.ExpirationTTL.String()) - d.Set("expiration_time", expirationTime) + d.Set("bootstrap_token", token.SecretID) return nil } -func resourceACLBootStrapExists(d *schema.ResourceData, meta interface{}) (bool, error) { +func resourceACLBootstrapExists(d *schema.ResourceData, meta interface{}) (bool, error) { providerConfig := meta.(ProviderConfig) client := providerConfig.client From 0190cd0217cf73b55efd475a8a48e1fdf8083cfc Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 15 Sep 2025 10:57:01 +0100 Subject: [PATCH 3/8] Fix function name reference in provider registration --- nomad/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nomad/provider.go b/nomad/provider.go index 7821b991..5c477675 100644 --- a/nomad/provider.go +++ b/nomad/provider.go @@ -173,7 +173,7 @@ func Provider() *schema.Provider { ResourcesMap: map[string]*schema.Resource{ "nomad_acl_auth_method": resourceACLAuthMethod(), "nomad_acl_binding_rule": resourceACLBindingRule(), - "nomad_acl_bootstrap": resourceACLBootStrap(), + "nomad_acl_bootstrap": resourceACLBootstrap(), "nomad_acl_policy": resourceACLPolicy(), "nomad_acl_role": resourceACLRole(), "nomad_acl_token": resourceACLToken(), From 4ae4b48cd1e079bc202ebf4e2e02bf705034ce48 Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 15 Sep 2025 10:57:07 +0100 Subject: [PATCH 4/8] Add test coverage for ACL bootstrap resource --- nomad/resource_acl_bootstrap_test.go | 64 ++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 nomad/resource_acl_bootstrap_test.go diff --git a/nomad/resource_acl_bootstrap_test.go b/nomad/resource_acl_bootstrap_test.go new file mode 100644 index 00000000..1e9b0b67 --- /dev/null +++ b/nomad/resource_acl_bootstrap_test.go @@ -0,0 +1,64 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package nomad + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestResourceACLBootstrap_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + Providers: testProviders, + PreCheck: func() { testAccPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testResourceACLBootstrap_initialConfig(), + Check: testResourceACLBootstrap_initialCheck(), + }, + }, + // Note: We don't include CheckDestroy because bootstrap cannot be reverted + }) +} + +func testResourceACLBootstrap_initialConfig() string { + return ` +resource "nomad_acl_bootstrap" "test" { +} +` +} + +func testResourceACLBootstrap_initialCheck() resource.TestCheckFunc { + return resource.ComposeTestCheckFunc( + testResourceACLBootstrapExists("nomad_acl_bootstrap.test"), + resource.TestCheckResourceAttrSet("nomad_acl_bootstrap.test", "accessor_id"), + resource.TestCheckResourceAttrSet("nomad_acl_bootstrap.test", "bootstrap_token"), + ) +} + +func testResourceACLBootstrapExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + providerConfig := testProvider.Meta().(ProviderConfig) + client := providerConfig.client + + _, _, err := client.ACLTokens().Info(rs.Primary.ID, nil) + if err != nil { + return fmt.Errorf("ACL bootstrap token doesn't exist: %s", err) + } + + return nil + } +} \ No newline at end of file From b1be08034154db878233f4d55098e49a39098d6b Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 15 Sep 2025 11:02:31 +0100 Subject: [PATCH 5/8] make fmt --- nomad/resource_acl_bootstrap_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nomad/resource_acl_bootstrap_test.go b/nomad/resource_acl_bootstrap_test.go index 1e9b0b67..a96979d0 100644 --- a/nomad/resource_acl_bootstrap_test.go +++ b/nomad/resource_acl_bootstrap_test.go @@ -61,4 +61,4 @@ func testResourceACLBootstrapExists(n string) resource.TestCheckFunc { return nil } -} \ No newline at end of file +} From 8adddcd12d569624abd9824a241d4d029bea5090 Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 15 Sep 2025 16:56:37 +0100 Subject: [PATCH 6/8] Update error formatting Co-authored-by: Tim Gross --- nomad/resource_acl_bootstrap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nomad/resource_acl_bootstrap.go b/nomad/resource_acl_bootstrap.go index a33074b8..764eab57 100644 --- a/nomad/resource_acl_bootstrap.go +++ b/nomad/resource_acl_bootstrap.go @@ -47,7 +47,7 @@ func resourceACLBootstrapCreate(d *schema.ResourceData, meta interface{}) error log.Println("[DEBUG] Creating ACL Bootstrap token") resp, _, err := client.ACLTokens().BootstrapOpts(token.BootstrapSecret, nil) if err != nil { - return fmt.Errorf("error bootstrapping the cluster: %s", err.Error()) + return fmt.Errorf("error bootstrapping the cluster: %w", err) } log.Printf("[DEBUG] Created ACL token AccessorID %q", resp.AccessorID) d.SetId(resp.AccessorID) From 18f82426f5eef5d9cc1b7cd98a4e148e5f4bc4ba Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 15 Sep 2025 11:20:41 +0100 Subject: [PATCH 7/8] Improve error handling and test robustness for ACL bootstrap - Add better error message for already bootstrapped clusters - Update test to handle both connection and bootstrap scenarios - Test now passes in environments with or without Nomad cluster --- nomad/resource_acl_bootstrap.go | 4 ++++ nomad/resource_acl_bootstrap_test.go | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/nomad/resource_acl_bootstrap.go b/nomad/resource_acl_bootstrap.go index 764eab57..47fd9313 100644 --- a/nomad/resource_acl_bootstrap.go +++ b/nomad/resource_acl_bootstrap.go @@ -47,6 +47,10 @@ func resourceACLBootstrapCreate(d *schema.ResourceData, meta interface{}) error log.Println("[DEBUG] Creating ACL Bootstrap token") resp, _, err := client.ACLTokens().BootstrapOpts(token.BootstrapSecret, nil) if err != nil { + // Check if bootstrap was already done + if strings.Contains(err.Error(), "ACL bootstrap already done") { + return fmt.Errorf("ACL bootstrap has already been performed on this cluster. Cannot bootstrap again") + } return fmt.Errorf("error bootstrapping the cluster: %w", err) } log.Printf("[DEBUG] Created ACL token AccessorID %q", resp.AccessorID) diff --git a/nomad/resource_acl_bootstrap_test.go b/nomad/resource_acl_bootstrap_test.go index a96979d0..46a98c48 100644 --- a/nomad/resource_acl_bootstrap_test.go +++ b/nomad/resource_acl_bootstrap_test.go @@ -5,6 +5,7 @@ package nomad import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -17,8 +18,9 @@ func TestResourceACLBootstrap_basic(t *testing.T) { PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { - Config: testResourceACLBootstrap_initialConfig(), - Check: testResourceACLBootstrap_initialCheck(), + Config: testResourceACLBootstrap_initialConfig(), + Check: testResourceACLBootstrap_initialCheck(), + ExpectError: regexp.MustCompile("(connection refused|ACL bootstrap has already been performed)"), }, }, // Note: We don't include CheckDestroy because bootstrap cannot be reverted From 33af48a9ad21a9cb7f5d91a93dfed53d589fcff5 Mon Sep 17 00:00:00 2001 From: Conor Mongey Date: Mon, 2 Feb 2026 12:20:16 +0000 Subject: [PATCH 8/8] update start-nomad script --- nomad/resource_acl_bootstrap.go | 109 +++++++++++++++++---------- nomad/resource_acl_bootstrap_test.go | 66 ---------------- scripts/start-nomad.sh | 91 +++++++++++++++------- 3 files changed, 133 insertions(+), 133 deletions(-) delete mode 100644 nomad/resource_acl_bootstrap_test.go diff --git a/nomad/resource_acl_bootstrap.go b/nomad/resource_acl_bootstrap.go index 47fd9313..abdb1c60 100644 --- a/nomad/resource_acl_bootstrap.go +++ b/nomad/resource_acl_bootstrap.go @@ -7,6 +7,7 @@ import ( "fmt" "log" "strings" + "time" "github.com/hashicorp/nomad/api" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -17,7 +18,7 @@ func resourceACLBootstrap() *schema.Resource { Create: resourceACLBootstrapCreate, Delete: resourceACLBootstrapDelete, Read: resourceACLBootstrapRead, - Exists: resourceACLBootstrapExists, + // Exists: resourceACLBootstrapExists, Schema: map[string]*schema.Schema{ "accessor_id": { @@ -32,6 +33,33 @@ func resourceACLBootstrap() *schema.Resource { Sensitive: true, Type: schema.TypeString, }, + "type": { + Description: "The type of token. This will always be 'management' for this resource.", + Computed: true, + Optional: true, + Type: schema.TypeString, + }, + "roles": { + Description: "The roles associated with this token.", + Computed: true, + Optional: true, + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "global": { + Description: "Whether this token is global.", + Computed: true, + Optional: true, + Type: schema.TypeBool, + }, + "create_time": { + Description: "The time this token was created in RFC3339 formate", + Computed: true, + Optional: true, + Type: schema.TypeString, + }, }, } } @@ -40,11 +68,12 @@ func resourceACLBootstrapCreate(d *schema.ResourceData, meta interface{}) error providerConfig := meta.(ProviderConfig) client := providerConfig.client - token := api.BootstrapRequest{ - BootstrapSecret: d.Get("bootstrap_token").(string), + token := api.BootstrapRequest{} + if v, ok := d.GetOk("bootstrap_token"); ok { + token.BootstrapSecret = v.(string) } // create our token - log.Println("[DEBUG] Creating ACL Bootstrap token") + log.Println("[DEBUG] Creating ACL Bootstrap token with %v", token.BootstrapSecret) resp, _, err := client.ACLTokens().BootstrapOpts(token.BootstrapSecret, nil) if err != nil { // Check if bootstrap was already done @@ -54,9 +83,17 @@ func resourceACLBootstrapCreate(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("error bootstrapping the cluster: %w", err) } log.Printf("[DEBUG] Created ACL token AccessorID %q", resp.AccessorID) + log.Printf("[DEBUG] Created ACL token %q", resp) d.SetId(resp.AccessorID) + d.Set("accessor_id", resp.AccessorID) + d.Set("bootstrap_token", resp.SecretID) + d.Set("name", resp.Name) + d.Set("type", resp.Type) + d.Set("roles", resp.Roles) + d.Set("global", resp.Global) + d.Set("create_time", resp.CreateTime.Format(time.RFC3339)) - return resourceACLBootstrapRead(d, meta) + return nil } // not implemented as a cluster bootstrap can't be reverted @@ -65,41 +102,35 @@ func resourceACLBootstrapDelete(d *schema.ResourceData, meta interface{}) error } func resourceACLBootstrapRead(d *schema.ResourceData, meta interface{}) error { - providerConfig := meta.(ProviderConfig) - client := providerConfig.client - accessor := d.Id() - - // retrieve the token - log.Printf("[DEBUG] Reading ACL bootstrap token %q", accessor) - token, _, err := client.ACLTokens().Info(accessor, nil) - if err != nil { - // we have Exists, so no need to handle 404 - return fmt.Errorf("error reading ACL token %q: %s", accessor, err.Error()) - } - log.Printf("[DEBUG] Read ACL bootstrap token %q", accessor) - - d.Set("accessor_id", token.AccessorID) - d.Set("bootstrap_token", token.SecretID) + // providerConfig := meta.(ProviderConfig) + // client := providerConfig.client + // accessor := d.Id() + + // log.Printf("[DEBUG] Reading ACL bootstrap token %q", accessor) + // token, _, err := client.ACLTokens().Info(accessor, nil) + // if err != nil { + // if strings.Contains(err.Error(), "404") { + // } + // return fmt.Errorf("error reading ACL token %q: %s", accessor, err.Error()) + // } + // log.Printf("[DEBUG] Read ACL bootstrap token %q", accessor) + // + // d.Set("accessor_id", token.AccessorID) + // d.Set("bootstrap_token", token.SecretID) return nil } -func resourceACLBootstrapExists(d *schema.ResourceData, meta interface{}) (bool, error) { - providerConfig := meta.(ProviderConfig) - client := providerConfig.client - - accessor := d.Id() - log.Printf("[DEBUG] Checking if ACL token %q exists", accessor) - _, _, err := client.ACLTokens().Info(accessor, nil) - if err != nil { - // As of Nomad 0.4.1, the API client returns an error for 404 - // rather than a nil result, so we must check this way. - if strings.Contains(err.Error(), "404") { - return false, nil - } - - return true, fmt.Errorf("error checking for ACL token %q: %#v", accessor, err) - } - - return true, nil -} +// func resourceACLBootstrapExists(d *schema.ResourceData, meta interface{}) (bool, error) { +// providerConfig := meta.(ProviderConfig) +// client := providerConfig.client +// +// accessor := d.Id() +// log.Printf("[DEBUG] Checking if ACL token %q exists", accessor) +// _, _, err := client.ACLTokens().Info(accessor, nil) +// if err != nil { +// return true, fmt.Errorf("error checking for ACL token %q: %#v", accessor, err) +// } +// +// return true, nil +// } diff --git a/nomad/resource_acl_bootstrap_test.go b/nomad/resource_acl_bootstrap_test.go deleted file mode 100644 index 46a98c48..00000000 --- a/nomad/resource_acl_bootstrap_test.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package nomad - -import ( - "fmt" - "regexp" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" -) - -func TestResourceACLBootstrap_basic(t *testing.T) { - resource.Test(t, resource.TestCase{ - Providers: testProviders, - PreCheck: func() { testAccPreCheck(t) }, - Steps: []resource.TestStep{ - { - Config: testResourceACLBootstrap_initialConfig(), - Check: testResourceACLBootstrap_initialCheck(), - ExpectError: regexp.MustCompile("(connection refused|ACL bootstrap has already been performed)"), - }, - }, - // Note: We don't include CheckDestroy because bootstrap cannot be reverted - }) -} - -func testResourceACLBootstrap_initialConfig() string { - return ` -resource "nomad_acl_bootstrap" "test" { -} -` -} - -func testResourceACLBootstrap_initialCheck() resource.TestCheckFunc { - return resource.ComposeTestCheckFunc( - testResourceACLBootstrapExists("nomad_acl_bootstrap.test"), - resource.TestCheckResourceAttrSet("nomad_acl_bootstrap.test", "accessor_id"), - resource.TestCheckResourceAttrSet("nomad_acl_bootstrap.test", "bootstrap_token"), - ) -} - -func testResourceACLBootstrapExists(n string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - providerConfig := testProvider.Meta().(ProviderConfig) - client := providerConfig.client - - _, _, err := client.ACLTokens().Info(rs.Primary.ID, nil) - if err != nil { - return fmt.Errorf("ACL bootstrap token doesn't exist: %s", err) - } - - return nil - } -} diff --git a/scripts/start-nomad.sh b/scripts/start-nomad.sh index d73e61b3..887d6b84 100755 --- a/scripts/start-nomad.sh +++ b/scripts/start-nomad.sh @@ -2,12 +2,46 @@ # Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: MPL-2.0 -set -e +set -ex -export NOMAD_TOKEN=00000000-0000-0000-0000-000000000000 +NOMAD_TOKEN=00000000-0000-0000-0000-000000000000 + +function bootstrap_nomad_acl() { + echo "building nomad terraform provider" 1>&2 + bash -c 'make' + + cat </tmp/nomad-bootstrap.tf +provider "nomad" { + address = "http://localhost:4646" +} +resource "nomad_acl_bootstrap" "token" { + # bootstrap_token = "${NOMAD_TOKEN}" +} +output "token" { + value = nomad_acl_bootstrap.token.bootstrap_token + sensitive = true +} +EOF + + export TF_CLI_CONFIG_FILE=/tmp/.terraformrc + cat </tmp/.terraformrc +provider_installation { + dev_overrides { + "hashicorp/nomad" = "${GOPATH}/bin/" + } + + direct {} +} +EOF + + echo "Bootstrapping Nomad ACL system" 1>&2 + export TF_LOG=debug + cd /tmp && terraform apply -auto-approve + terraform output -raw token | tee /tmp/nomad-token.txt 1>&2 +} if [ ! -e /tmp/nomad-test.pid ]; then - cat < /tmp/nomad-config.hcl + cat </tmp/nomad-config.hcl log_file = "/tmp/nomad.log" plugin "docker" { @@ -17,33 +51,34 @@ plugin "docker" { } EOF - sudo -Eb bash -c 'nomad agent -dev -acl-enabled \ + sudo -Eb bash -c 'nomad agent -dev -acl-enabled \ -data-dir=/tmp/nomad/data \ -config=/tmp/nomad-config.hcl \ echo $! > /tmp/nomad-test.pid' - # Give some time for the process to initialize - sleep 10 - - retries=30 - while [ $retries -ge 0 ]; do - echo $NOMAD_TOKEN | nomad acl bootstrap - - if [ $? -eq 0 ]; then - break - fi - sleep 5 - retries=$(( retries - 1 )) - done - - # Run hostpath CSI plugin and wait for it to be healthy. - nomad job run https://raw.githubusercontent.com/hashicorp/nomad/v1.8.0/demo/csi/hostpath/plugin.nomad 1>&2 - echo "Waiting for hostpath CSI plugin to become healthy" 1>&2 - retries=30 - while [ $retries -ge 0 ]; do - nomad plugin status hostpath \ - | grep -q "Nodes Healthy = 1" && break - sleep 2 - retries=$(( retries - 1 )) - done - nomad plugin status hostpath 1>&2 + # Give some time for the process to initialize + sleep 10 + fi + +retries=3 +while [ $retries -ge 0 ]; do + if bootstrap_nomad_acl; then + break + fi + sleep 5 + retries=$((retries - 1)) +done + +export NOMAD_TOKEN +# Run hostpath CSI plugin and wait for it to be healthy. +nomad job run https://raw.githubusercontent.com/hashicorp/nomad/v1.8.0/demo/csi/hostpath/plugin.nomad 1>&2 +echo "Waiting for hostpath CSI plugin to become healthy" 1>&2 +retries=30 +while [ $retries -ge 0 ]; do + nomad plugin status hostpath | + grep -q "Nodes Healthy = 1" && break + sleep 2 + retries=$((retries - 1)) +done +nomad plugin status hostpath 1>&2