-
Notifications
You must be signed in to change notification settings - Fork 101
Add nomad_acl_bootstrap resource #553
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
base: main
Are you sure you want to change the base?
Changes from all commits
acc9d52
913d3dd
0190cd0
4ae4b48
b1be080
8adddcd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,101 @@ | ||||||
// Copyright (c) HashiCorp, Inc. | ||||||
// SPDX-License-Identifier: MPL-2.0 | ||||||
|
||||||
package nomad | ||||||
|
||||||
import ( | ||||||
"fmt" | ||||||
"log" | ||||||
"strings" | ||||||
|
||||||
"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 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can leave comments like this out, especially given the log following right behind it.
Suggested change
|
||||||
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: %w", err) | ||||||
} | ||||||
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()) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
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. | ||||||
Comment on lines
+91
to
+92
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can probably leave this comment out, or at least remove the "as of Nomad 0.4.1" bit (I realize this is probably just copy-pasted from the other ACL resources but no need to keep adding it). |
||||||
if strings.Contains(err.Error(), "404") { | ||||||
return false, nil | ||||||
} | ||||||
|
||||||
return true, fmt.Errorf("error checking for ACL token %q: %#v", accessor, err) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
} | ||||||
|
||||||
return true, nil | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only support recent versions of Go, so any place we have
interface{}
we can useany
now: