Skip to content

Commit

Permalink
feat: add a field docker_plugin.name
Browse files Browse the repository at this point in the history
  • Loading branch information
suzuki-shunsuke committed Jan 8, 2021
1 parent 7a7aee3 commit b82956b
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 75 deletions.
17 changes: 12 additions & 5 deletions docker/resource_docker_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ func resourceDockerPlugin() *schema.Resource {
State: schema.ImportStatePassthrough,
},
Schema: map[string]*schema.Schema{
"plugin_reference": {
Type: schema.TypeString,
Description: "Docker Plugin Reference",
Required: true,
ForceNew: true,
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Docker Plugin name",
DiffSuppressFunc: diffSuppressFuncPluginName,
ValidateFunc: validateFuncPluginName,
},
"alias": {
Type: schema.TypeString,
Expand Down Expand Up @@ -68,6 +70,11 @@ func resourceDockerPlugin() *schema.Resource {
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"plugin_reference": {
Type: schema.TypeString,
Description: "Docker Plugin Reference",
Computed: true,
},

"force_destroy": {
Type: schema.TypeBool,
Expand Down
39 changes: 34 additions & 5 deletions docker/resource_docker_plugin_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"log"
"strings"

"github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down Expand Up @@ -35,6 +36,33 @@ func complementTag(image string) string {
return image + ":latest"
}

func normalizePluginName(name string) (string, error) {
ref, err := reference.ParseAnyReference(name)
if err != nil {
return "", fmt.Errorf("parse the plugin name: %w", err)
}
return complementTag(ref.String()), nil
}

func diffSuppressFuncPluginName(k, oldV, newV string, d *schema.ResourceData) bool {
o, err := normalizePluginName(oldV)
if err != nil {
return false
}
n, err := normalizePluginName(newV)
if err != nil {
return false
}
return o == n
}

func validateFuncPluginName(val interface{}, key string) (warns []string, errs []error) {
if _, err := normalizePluginName(val.(string)); err != nil {
return warns, append(errs, fmt.Errorf("%s is invalid: %w", key, err))
}
return
}

func getDockerPluginGrantPermissions(src interface{}) func(types.PluginPrivileges) (bool, error) {
grantPermissionsSet := src.(*schema.Set)
grantPermissions := make(map[string]map[string]struct{}, grantPermissionsSet.Len())
Expand Down Expand Up @@ -69,11 +97,11 @@ func getDockerPluginGrantPermissions(src interface{}) func(types.PluginPrivilege
func resourceDockerPluginCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ProviderConfig).DockerClient
ctx := context.Background()
pluginRef := d.Get("plugin_reference").(string)
pluginName := d.Get("name").(string)
alias := d.Get("alias").(string)
log.Printf("[DEBUG] Install a Docker plugin " + pluginRef)
log.Printf("[DEBUG] Install a Docker plugin " + pluginName)
opts := types.PluginInstallOptions{
RemoteRef: pluginRef,
RemoteRef: pluginName,
AcceptAllPermissions: d.Get("grant_all_permissions").(bool),
Disabled: !d.Get("enabled").(bool),
// TODO support other settings
Expand All @@ -84,10 +112,10 @@ func resourceDockerPluginCreate(d *schema.ResourceData, meta interface{}) error
}
body, err := client.PluginInstall(ctx, alias, opts)
if err != nil {
return fmt.Errorf("install a Docker plugin "+pluginRef+": %w", err)
return fmt.Errorf("install a Docker plugin "+pluginName+": %w", err)
}
_, _ = ioutil.ReadAll(body)
key := pluginRef
key := pluginName
if alias != "" {
key = alias
}
Expand All @@ -103,6 +131,7 @@ func setDockerPlugin(d *schema.ResourceData, plugin *types.Plugin) {
d.SetId(plugin.ID)
d.Set("plugin_reference", plugin.PluginReference)
d.Set("alias", plugin.Name)
d.Set("name", plugin.PluginReference)
d.Set("enabled", plugin.Enabled)
// TODO support other settings
// https://docs.docker.com/engine/reference/commandline/plugin_set/#extended-description
Expand Down
42 changes: 24 additions & 18 deletions docker/resource_docker_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func TestAccDockerPlugin_basic(t *testing.T) {
ResourceName: resourceName,
Config: testAccDockerPluginMinimum,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "plugin_reference", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "alias", "tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
Expand All @@ -160,6 +161,7 @@ func TestAccDockerPlugin_basic(t *testing.T) {
ResourceName: resourceName,
Config: testAccDockerPluginAlias,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "plugin_reference", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "alias", "sample:latest"),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
Expand All @@ -169,6 +171,7 @@ func TestAccDockerPlugin_basic(t *testing.T) {
ResourceName: resourceName,
Config: testAccDockerPluginDisableWhenSet,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "plugin_reference", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "alias", "sample:latest"),
resource.TestCheckResourceAttr(resourceName, "enabled", "true"),
Expand All @@ -181,6 +184,7 @@ func TestAccDockerPlugin_basic(t *testing.T) {
ResourceName: resourceName,
Config: testAccDockerPluginDisabled,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "plugin_reference", "docker.io/tiborvass/sample-volume-plugin:latest"),
resource.TestCheckResourceAttr(resourceName, "alias", "sample:latest"),
resource.TestCheckResourceAttr(resourceName, "enabled", "false"),
Expand Down Expand Up @@ -208,6 +212,7 @@ func TestAccDockerPlugin_grantAllPermissions(t *testing.T) {
ResourceName: resourceName,
Config: testAccDockerPluginGrantAllPermissions,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "docker.io/vieux/sshfs:latest"),
resource.TestCheckResourceAttr(resourceName, "plugin_reference", "docker.io/vieux/sshfs:latest"),
resource.TestCheckResourceAttr(resourceName, "alias", "vieux/sshfs:latest"),
resource.TestCheckResourceAttr(resourceName, "grant_all_permissions", "true"),
Expand All @@ -231,6 +236,7 @@ func TestAccDockerPlugin_grantPermissions(t *testing.T) {
ResourceName: resourceName,
Config: testAccDockerPluginGrantPermissions,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "name", "docker.io/vieux/sshfs:latest"),
resource.TestCheckResourceAttr(resourceName, "plugin_reference", "docker.io/vieux/sshfs:latest"),
resource.TestCheckResourceAttr(resourceName, "alias", "vieux/sshfs:latest"),
),
Expand All @@ -245,38 +251,38 @@ func TestAccDockerPlugin_grantPermissions(t *testing.T) {

const testAccDockerPluginMinimum = `
resource "docker_plugin" "test" {
plugin_reference = "docker.io/tiborvass/sample-volume-plugin:latest"
force_destroy = true
name = "docker.io/tiborvass/sample-volume-plugin:latest"
force_destroy = true
}`

const testAccDockerPluginAlias = `
resource "docker_plugin" "test" {
plugin_reference = "docker.io/tiborvass/sample-volume-plugin:latest"
name = "docker.io/tiborvass/sample-volume-plugin:latest"
alias = "sample:latest"
force_destroy = true
}`

const testAccDockerPluginDisableWhenSet = `
resource "docker_plugin" "test" {
plugin_reference = "docker.io/tiborvass/sample-volume-plugin:latest"
alias = "sample:latest"
grant_all_permissions = true
force_destroy = true
enable_timeout = 60
name = "docker.io/tiborvass/sample-volume-plugin:latest"
alias = "sample:latest"
grant_all_permissions = true
force_destroy = true
enable_timeout = 60
env = [
"DEBUG=1"
]
}`

const testAccDockerPluginDisabled = `
resource "docker_plugin" "test" {
plugin_reference = "docker.io/tiborvass/sample-volume-plugin:latest"
alias = "sample:latest"
enabled = false
grant_all_permissions = true
force_destroy = true
force_disable = true
enable_timeout = 60
name = "docker.io/tiborvass/sample-volume-plugin:latest"
alias = "sample:latest"
enabled = false
grant_all_permissions = true
force_destroy = true
force_disable = true
enable_timeout = 60
env = [
"DEBUG=1"
]
Expand All @@ -285,16 +291,16 @@ resource "docker_plugin" "test" {
// To install this plugin, it is required to grant required permissions.
const testAccDockerPluginGrantAllPermissions = `
resource "docker_plugin" "test" {
plugin_reference = "docker.io/vieux/sshfs:latest"
name = "docker.io/vieux/sshfs:latest"
grant_all_permissions = true
force_destroy = true
}`

// To install this plugin, it is required to grant required permissions.
const testAccDockerPluginGrantPermissions = `
resource "docker_plugin" "test" {
plugin_reference = "docker.io/vieux/sshfs:latest"
force_destroy = true
name = "vieux/sshfs"
force_destroy = true
grant_permissions {
name = "network"
value = [
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ require (
github.com/Microsoft/hcsshim v0.8.9 // indirect
github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe // indirect
github.com/docker/cli v0.0.0-20200303215952-eb310fca4956 // v19.03.8
github.com/docker/distribution v0.0.0-20180522175653-f0cc92778478 // indirect
github.com/docker/distribution v0.0.0-20180522175653-f0cc92778478
github.com/docker/docker v0.7.3-0.20190525203055-f25e0c6f3093
github.com/docker/docker-credential-helpers v0.6.3
github.com/docker/go-connections v0.4.0
Expand Down
53 changes: 7 additions & 46 deletions website/docs/r/plugin.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ Manages the lifecycle of a Docker plugin.

```hcl
resource "docker_plugin" "sample-volume-plugin" {
plugin_reference = "docker.io/tiborvass/sample-volume-plugin:latest"
name = "docker.io/tiborvass/sample-volume-plugin:latest"
}
```

```hcl
resource "docker_plugin" "sample-volume-plugin" {
plugin_reference = "docker.io/tiborvass/sample-volume-plugin:latest"
alias = "sample-volume-plugin:latest"
name = "tiborvass/sample-volume-plugin"
alias = "sample-volume-plugin"
enabled = false
grant_all_permissions = true
force_destroy = true
Expand All @@ -37,7 +37,7 @@ resource "docker_plugin" "sample-volume-plugin" {

The following arguments are supported:

* `plugin_reference` - (Required, string, Forces new resource) The plugin reference. The registry path and image tag should not be omitted. See [plugin_references, alias](#plugin-references-alias-1) below for details.
* `name` - (Required, string, Forces new resource) The plugin name. If the tag is omitted, `:latest` is complemented to the attribute value.
* `alias` - (Optional, string, Forces new resource) The alias of the Docker plugin. If the tag is omitted, `:latest` is complemented to the attribute value.
* `enabled` - (Optional, boolean) If true, the plugin is enabled. The default value is `true`.
* `grant_all_permissions` - (Optional, boolean) If true, grant all permissions necessary to run the plugin. This attribute conflicts with `grant_permissions`.
Expand All @@ -47,47 +47,6 @@ The following arguments are supported:
* `enable_timeout` - (Optional, int) HTTP client timeout to enable the plugin.
* `force_disable` - (Optional, boolean) If true, then the plugin is disabled forcibly when the plugin is disabled.

<a id="plugin-references-alias-1"></a>
## plugin_reference

`plugin_reference` must be full path. Otherwise, after `terraform apply` is run, there would be diffs of them.

For example,

```hcl
resource "docker_plugin" "sample-volume-plugin" {
plugin_reference = "tiborvass/sample-volume-plugin" # must be "docker.io/tiborvass/sample-volume-plugin:latest"
alias = "sample"
}
```

```sh
$ terraform apply # a plugin is installed

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

$ terraform plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

# docker_plugin.sample-volume-plugin must be replaced
-/+ resource "docker_plugin" "sample-volume-plugin" {
~ alias = "sample:latest" -> "sample:latest"
- enabled = false -> null
~ env = [
- "DEBUG=0",
] -> (known after apply)
~ id = "27784976e1471c1e473a901a0a02055ddc8bc1c9dec9c44d81a49d516c0c28f9" -> (known after apply)
~ plugin_reference = "docker.io/tiborvass/sample-volume-plugin:latest" -> "tiborvass/sample-volume-plugin" # forces replacement
}

Plan: 1 to add, 0 to change, 1 to destroy.
```

<a id="grant-permissions-1"></a>
## grant_permissions

Expand All @@ -101,7 +60,7 @@ Example:

```hcl
resource "docker_plugin" "sshfs" {
plugin_reference = "docker.io/vieux/sshfs:latest"
name = "docker.io/vieux/sshfs:latest"
grant_permissions {
name = "network"
value = [
Expand Down Expand Up @@ -132,6 +91,8 @@ resource "docker_plugin" "sshfs" {

## Attributes Reference

* `plugin_reference` - (string) The plugin reference.

## Import

Docker plugins can be imported using the long id, e.g. for a plugin `tiborvass/sample-volume-plugin:latest`:
Expand Down

0 comments on commit b82956b

Please sign in to comment.