Skip to content

Commit

Permalink
job: import jobs from non-default namespace (#408)
Browse files Browse the repository at this point in the history
* import: add helper to import namespaced resources

`nomad_job`, `nomad_csi_volume`, and `nomad_csi_volume_registration` do
not have the namespace as part of their state ID. This makes it
impossible to import them if they are registered in a non-default
namespace since only the ID is provided to the import function.

This commit adds a new helper that imports using an ID with the format
`<id>@<namespace>`. Since `@` is not a valid character for namespaces,
the last `@` character (if found) represents the separator.

* changelog: add entry for #408

* chore: add missing copyright header

* provider: fix namespaced importer

Importing namespaced resources require a namespace to be passed. Without
this requirement jobs such as `a@b` become ambiguous as it's not
possible to determine if the user intention was to import the job named
`a` from namespace `b` or job `a@b` on namespace `default`. By requiring
a namespace to be set this ambiguity is solved.

Additionally, Terraform automatically refreshes the state after an
import, so there is no need to call the `Read` method manually on
import. Doing so can also have unintended consequences, as the provider
deletes resources from state in case of a `404`, resulting in a
Terraform error when trying to import resources that don't exist.

* apply code review
  • Loading branch information
lgfa29 authored Dec 19, 2023
1 parent 5afd8e7 commit 1b74304
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ IMPROVEMENTS:
* provider: update Go to 1.21.5 ([#399](https://github.com/hashicorp/terraform-provider-nomad/pull/399))
* resource/resource_acl_auth_method: add support for `token_name_format` ([#403](https://github.com/hashicorp/terraform-provider-nomad/pull/403))
* resource/nomad_csi_volume: changes to `capacity_min` or `capacity_max` may now expand the volume instead of forcing replacement,
* resource/nomad_csi_volume: update import key to be `<volume id>@<namespace>` to allow importing volumes from namespaces other than `default` ([#408](https://github.com/hashicorp/terraform-provider-nomad/pull/408))
* resource/nomad_csi_volume_registration: update import key to be `<volume id>@<namespace>` to allow importing volume registrations from namespaces other than `default` ([#408](https://github.com/hashicorp/terraform-provider-nomad/pull/408))
on Nomad version 1.6.3 or later, if the CSI plugin supports it ([#382](https://github.com/hashicorp/terraform-provider-nomad/pull/382))
* resource/nomad_job: Add `rerun_if_dead` attribute to allow forcing a job to run again if it's marked as `dead`. ([#407](https://github.com/hashicorp/terraform-provider-nomad/pull/407))
* resource/nomad_job: update import key to be `<job id>@<namespace>` to allow importing jobs from namespaces other than `default` ([#408](https://github.com/hashicorp/terraform-provider-nomad/pull/408))

BUG FIXES:
* resource/nomad_acl_policy: fixed a bug where the namespace would be incorrectly calculated from a job identity ([#396](https://github.com/hashicorp/terraform-provider-nomad/pull/396))
Expand Down
42 changes: 42 additions & 0 deletions nomad/helper/import.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package helper

import (
"context"
"errors"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

var (
missingNamespaceImportErr = errors.New("missing namespace, the import ID should follow the pattern <id>@<namespace>")
missingIDImportErr = errors.New("missing resource ID, the import ID should follow the pattern <id>@<namespace>")
)

// NamespacedImporterContext imports a namespaced resource that doesn't have
// its namespace as part of the Terraform resource ID.
func NamespacedImporterContext(_ context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) {
namespacedID := d.Id()
sepIdx := strings.LastIndex(namespacedID, "@")
if sepIdx == -1 {
return nil, missingNamespaceImportErr
}

ns := namespacedID[sepIdx+1:]
if len(ns) == 0 {
return nil, missingNamespaceImportErr
}

id := namespacedID[:sepIdx]
if len(id) == 0 {
return nil, missingIDImportErr
}

d.SetId(id)
d.Set("namespace", ns)

return []*schema.ResourceData{d}, nil
}
2 changes: 1 addition & 1 deletion nomad/resource_csi_volume.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func resourceCSIVolume() *schema.Resource {
},

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: helper.NamespacedImporterContext,
},

Schema: map[string]*schema.Schema{
Expand Down
2 changes: 1 addition & 1 deletion nomad/resource_csi_volume_registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func resourceCSIVolumeRegistration() *schema.Resource {
},

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: helper.NamespacedImporterContext,
},

Schema: map[string]*schema.Schema{
Expand Down
3 changes: 2 additions & 1 deletion nomad/resource_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/hashicorp/nomad/jobspec2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-nomad/nomad/helper"
)

func resourceJob() *schema.Resource {
Expand All @@ -36,7 +37,7 @@ func resourceJob() *schema.Resource {
},

Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
StateContext: helper.NamespacedImporterContext,
},

Schema: map[string]*schema.Schema{
Expand Down
17 changes: 17 additions & 0 deletions website/docs/r/csi_volume.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,22 @@ configuration options.
- `create` `(string: "10m")` - Timeout when creating or updating a new CSI volume.
- `delete` `(string: "10m")` - Timeout when deleting a CSI volume.

## Importing CSI Volumes

CSI volumes are imported using the pattern `<volume ID>@<namespace>` .

```console
$ terraform import nomad_csi_volume.mysql mysql@my-namespace
nomad_csi_volume.mysql: Importing from ID "mysql@my-namespace"...
nomad_csi_volume.mysql: Import prepared!
Prepared nomad_csi_volume for import
nomad_csi_volume.mysql: Refreshing state... [id=mysql@my-namespace]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```

[tf_docs_timeouts]: https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts
[tf_docs_prevent_destroy]: https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#prevent_destroy
18 changes: 18 additions & 0 deletions website/docs/r/csi_volume_registration.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,22 @@ can be referenced:
- `create` `(string: "10m")` - Timeout when registering a new CSI volume.
- `delete` `(string: "10m")` - Timeout when deregistering a CSI volume.

## Importing CSI Volume Registrations

CSI volume registrations are imported using the pattern
`<volume ID>@<namespace>`.

```console
$ terraform import nomad_csi_volume.mysql mysql@my-namespace
nomad_csi_volume_registration.mysql: Importing from ID "mysql@my-namespace"...
nomad_csi_volume_registration.mysql: Import prepared!
Prepared nomad_csi_volume_registration for import
nomad_csi_volume_registration.mysql: Refreshing state... [id=mysql@my-namespace]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```

[tf_docs_timeouts]: https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts
17 changes: 17 additions & 0 deletions website/docs/r/job.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,23 @@ options when [`detach`](#detach) is set to `false`:
- `create` `(string: "5m")` - Timeout when registering a new job.
- `update` `(string: "5m")` - Timeout when updating an existing job.

## Importing Jobs

Jobs are imported using the pattern `<job ID>@<namespace>`.

```console
$ terraform import nomad_job.example example@my-namespace
nomad_job.example: Importing from ID "example@my-namespace"...
nomad_job.example: Import prepared!
Prepared nomad_job for import
nomad_job.example: Refreshing state... [id=example@my-namespace]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```

[tf_docs_timeouts]: https://www.terraform.io/docs/configuration/blocks/resources/syntax.html#operation-timeouts
[tf_docs_templatefile]: https://www.terraform.io/docs/configuration/functions/templatefile.html
[tf_docs_string_template]: https://www.terraform.io/language/expressions/strings#string-templates

0 comments on commit 1b74304

Please sign in to comment.