mirror of
https://github.com/kreuzwerker/terraform-provider-docker.git
synced 2025-12-30 19:49:50 -05:00
parent
0ef85ad13f
commit
c927a8c19f
13 changed files with 1047 additions and 16 deletions
80
docker/data_source_docker_plugin.go
Normal file
80
docker/data_source_docker_plugin.go
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
)
|
||||
|
||||
func dataSourceDockerPlugin() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Read: dataSourceDockerPluginRead,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"id": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
"alias": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Docker Plugin alias",
|
||||
},
|
||||
|
||||
"plugin_reference": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Docker Plugin Reference",
|
||||
Computed: true,
|
||||
},
|
||||
"enabled": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
},
|
||||
"grant_all_permissions": {
|
||||
Type: schema.TypeBool,
|
||||
Computed: true,
|
||||
Description: "If true, grant all permissions necessary to run the plugin",
|
||||
},
|
||||
"env": {
|
||||
Type: schema.TypeSet,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var errDataSourceKeyIsMissing = errors.New("One of id or alias must be assigned")
|
||||
|
||||
func getDataSourcePluginKey(d *schema.ResourceData) (string, error) {
|
||||
id, idOK := d.GetOk("id")
|
||||
alias, aliasOK := d.GetOk("alias")
|
||||
if idOK {
|
||||
if aliasOK {
|
||||
return "", errDataSourceKeyIsMissing
|
||||
}
|
||||
return id.(string), nil
|
||||
}
|
||||
if aliasOK {
|
||||
return alias.(string), nil
|
||||
}
|
||||
return "", errDataSourceKeyIsMissing
|
||||
}
|
||||
|
||||
func dataSourceDockerPluginRead(d *schema.ResourceData, meta interface{}) error {
|
||||
key, err := getDataSourcePluginKey(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client := meta.(*ProviderConfig).DockerClient
|
||||
ctx := context.Background()
|
||||
plugin, _, err := client.PluginInspectWithRaw(ctx, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("inspect a Docker plugin "+key+": %w", err)
|
||||
}
|
||||
|
||||
setDockerPlugin(d, plugin)
|
||||
return nil
|
||||
}
|
||||
39
docker/data_source_docker_plugin_test.go
Normal file
39
docker/data_source_docker_plugin_test.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccDockerPluginDataSource_basic(t *testing.T) {
|
||||
pluginName := "tiborvass/sample-volume-plugin"
|
||||
// This fails if the plugin is already installed.
|
||||
if err := exec.Command("docker", "plugin", "install", pluginName).Run(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
if err := exec.Command("docker", "plugin", "rm", "-f", pluginName).Run(); err != nil {
|
||||
t.Logf("failed to remove the Docker plugin %s: %v", pluginName, err)
|
||||
}
|
||||
}()
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccDockerPluginDataSourceTest,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("data.docker_plugin.test", "plugin_reference", "docker.io/tiborvass/sample-volume-plugin:latest"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const testAccDockerPluginDataSourceTest = `
|
||||
data "docker_plugin" "test" {
|
||||
alias = "tiborvass/sample-volume-plugin:latest"
|
||||
}
|
||||
`
|
||||
|
|
@ -109,11 +109,13 @@ func Provider() terraform.ResourceProvider {
|
|||
"docker_config": resourceDockerConfig(),
|
||||
"docker_secret": resourceDockerSecret(),
|
||||
"docker_service": resourceDockerService(),
|
||||
"docker_plugin": resourceDockerPlugin(),
|
||||
},
|
||||
|
||||
DataSourcesMap: map[string]*schema.Resource{
|
||||
"docker_registry_image": dataSourceDockerRegistryImage(),
|
||||
"docker_network": dataSourceDockerNetwork(),
|
||||
"docker_plugin": dataSourceDockerPlugin(),
|
||||
},
|
||||
|
||||
ConfigureFunc: providerConfigure,
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ func resourceDockerContainer() *schema.Resource {
|
|||
},
|
||||
"driver_name": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Name of the driver to use to create the volume.",
|
||||
Description: "Name of the driver to use to create the volume",
|
||||
Optional: true,
|
||||
},
|
||||
"driver_options": {
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ func resourceDockerContainerV1() *schema.Resource {
|
|||
},
|
||||
"driver_name": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Name of the driver to use to create the volume.",
|
||||
Description: "Name of the driver to use to create the volume",
|
||||
Optional: true,
|
||||
},
|
||||
"driver_options": {
|
||||
|
|
|
|||
95
docker/resource_docker_plugin.go
Normal file
95
docker/resource_docker_plugin.go
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
)
|
||||
|
||||
func resourceDockerPlugin() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceDockerPluginCreate,
|
||||
Read: resourceDockerPluginRead,
|
||||
Update: resourceDockerPluginUpdate,
|
||||
Delete: resourceDockerPluginDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
Description: "Docker Plugin name",
|
||||
DiffSuppressFunc: diffSuppressFuncPluginName,
|
||||
ValidateFunc: validateFuncPluginName,
|
||||
},
|
||||
"alias": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Description: "Docker Plugin alias",
|
||||
DiffSuppressFunc: func(k, oldV, newV string, d *schema.ResourceData) bool {
|
||||
return complementTag(oldV) == complementTag(newV)
|
||||
},
|
||||
},
|
||||
"enabled": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Default: true,
|
||||
},
|
||||
"grant_all_permissions": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "If true, grant all permissions necessary to run the plugin",
|
||||
ConflictsWith: []string{"grant_permissions"},
|
||||
},
|
||||
"grant_permissions": {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
ConflictsWith: []string{"grant_all_permissions"},
|
||||
Set: dockerPluginGrantPermissionsSetFunc,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"value": {
|
||||
Type: schema.TypeSet,
|
||||
Required: true,
|
||||
Elem: &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"env": {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
"plugin_reference": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Docker Plugin Reference",
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"force_destroy": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
},
|
||||
"enable_timeout": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
Description: "HTTP client timeout to enable the plugin",
|
||||
},
|
||||
"force_disable": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "If true, then the plugin is disabled forcibly when the plugin is disabled",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
262
docker/resource_docker_plugin_funcs.go
Normal file
262
docker/resource_docker_plugin_funcs.go
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"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"
|
||||
)
|
||||
|
||||
func getDockerPluginEnv(src interface{}) []string {
|
||||
if src == nil {
|
||||
return nil
|
||||
}
|
||||
b := src.(*schema.Set)
|
||||
envs := make([]string, b.Len())
|
||||
for i, a := range b.List() {
|
||||
envs[i] = a.(string)
|
||||
}
|
||||
return envs
|
||||
}
|
||||
|
||||
func dockerPluginGrantPermissionsSetFunc(v interface{}) int {
|
||||
return schema.HashString(v.(map[string]interface{})["name"].(string))
|
||||
}
|
||||
|
||||
func complementTag(image string) string {
|
||||
if strings.Contains(image, ":") {
|
||||
return image
|
||||
}
|
||||
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())
|
||||
for _, b := range grantPermissionsSet.List() {
|
||||
c := b.(map[string]interface{})
|
||||
name := c["name"].(string)
|
||||
values := c["value"].(*schema.Set)
|
||||
grantPermission := make(map[string]struct{}, values.Len())
|
||||
for _, value := range values.List() {
|
||||
grantPermission[value.(string)] = struct{}{}
|
||||
}
|
||||
grantPermissions[name] = grantPermission
|
||||
}
|
||||
return func(privileges types.PluginPrivileges) (bool, error) {
|
||||
for _, privilege := range privileges {
|
||||
grantPermission, nameOK := grantPermissions[privilege.Name]
|
||||
if !nameOK {
|
||||
log.Print("[DEBUG] to install the plugin, the following permissions are required: " + privilege.Name)
|
||||
return false, nil
|
||||
}
|
||||
for _, value := range privilege.Value {
|
||||
if _, ok := grantPermission[value]; !ok {
|
||||
log.Print("[DEBUG] to install the plugin, the following permissions are required: " + privilege.Name + " " + value)
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
func resourceDockerPluginCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*ProviderConfig).DockerClient
|
||||
ctx := context.Background()
|
||||
pluginName := d.Get("name").(string)
|
||||
alias := d.Get("alias").(string)
|
||||
log.Printf("[DEBUG] Install a Docker plugin " + pluginName)
|
||||
opts := types.PluginInstallOptions{
|
||||
RemoteRef: pluginName,
|
||||
AcceptAllPermissions: d.Get("grant_all_permissions").(bool),
|
||||
Disabled: !d.Get("enabled").(bool),
|
||||
// TODO support other settings
|
||||
Args: getDockerPluginEnv(d.Get("env")),
|
||||
}
|
||||
if v, ok := d.GetOk("grant_permissions"); ok {
|
||||
opts.AcceptPermissionsFunc = getDockerPluginGrantPermissions(v)
|
||||
}
|
||||
body, err := client.PluginInstall(ctx, alias, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("install a Docker plugin "+pluginName+": %w", err)
|
||||
}
|
||||
_, _ = ioutil.ReadAll(body)
|
||||
key := pluginName
|
||||
if alias != "" {
|
||||
key = alias
|
||||
}
|
||||
plugin, _, err := client.PluginInspectWithRaw(ctx, key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("inspect a Docker plugin "+key+": %w", err)
|
||||
}
|
||||
setDockerPlugin(d, plugin)
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
// source of mounts .Settings.Mounts
|
||||
// path of devices .Settings.Devices
|
||||
// args .Settings.Args
|
||||
d.Set("env", plugin.Settings.Env)
|
||||
}
|
||||
|
||||
func resourceDockerPluginRead(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*ProviderConfig).DockerClient
|
||||
ctx := context.Background()
|
||||
pluginID := d.Id()
|
||||
plugin, _, err := client.PluginInspectWithRaw(ctx, pluginID)
|
||||
if err != nil {
|
||||
log.Printf("[DEBUG] Inspect a Docker plugin "+pluginID+": %w", err)
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
setDockerPlugin(d, plugin)
|
||||
return nil
|
||||
}
|
||||
|
||||
func disablePlugin(ctx context.Context, d *schema.ResourceData, cl *client.Client) error {
|
||||
pluginID := d.Id()
|
||||
log.Printf("[DEBUG] Disable a Docker plugin " + pluginID)
|
||||
if err := cl.PluginDisable(ctx, pluginID, types.PluginDisableOptions{
|
||||
Force: d.Get("force_disable").(bool),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("disable the Docker plugin "+pluginID+": %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func enablePlugin(ctx context.Context, d *schema.ResourceData, cl *client.Client) error {
|
||||
pluginID := d.Id()
|
||||
log.Print("[DEBUG] Enable a Docker plugin " + pluginID)
|
||||
if err := cl.PluginEnable(ctx, pluginID, types.PluginEnableOptions{
|
||||
Timeout: d.Get("enable_timeout").(int),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("enable the Docker plugin "+pluginID+": %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pluginSet(ctx context.Context, d *schema.ResourceData, cl *client.Client) error {
|
||||
pluginID := d.Id()
|
||||
log.Printf("[DEBUG] Update settings of a Docker plugin " + pluginID)
|
||||
// currently, only environment variables are supported.
|
||||
// TODO support other args
|
||||
// https://docs.docker.com/engine/reference/commandline/plugin_set/#extended-description
|
||||
// source of mounts .Settings.Mounts
|
||||
// path of devices .Settings.Devices
|
||||
// args .Settings.Args
|
||||
if err := cl.PluginSet(ctx, pluginID, getDockerPluginEnv(d.Get("env"))); err != nil {
|
||||
return fmt.Errorf("modifiy settings for the Docker plugin "+pluginID+": %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pluginUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) (gErr error) {
|
||||
cl := meta.(*ProviderConfig).DockerClient
|
||||
o, n := d.GetChange("enabled")
|
||||
oldEnabled, newEnabled := o.(bool), n.(bool)
|
||||
if d.HasChange("env") {
|
||||
if oldEnabled {
|
||||
// To update the plugin setttings, the plugin must be disabled
|
||||
if err := disablePlugin(ctx, d, cl); err != nil {
|
||||
return err
|
||||
}
|
||||
if newEnabled {
|
||||
defer func() {
|
||||
if err := enablePlugin(ctx, d, cl); err != nil {
|
||||
if gErr == nil {
|
||||
gErr = err
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
if err := pluginSet(ctx, d, cl); err != nil {
|
||||
return err
|
||||
}
|
||||
if !oldEnabled && newEnabled {
|
||||
if err := enablePlugin(ctx, d, cl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// update only "enabled"
|
||||
if d.HasChange("enabled") {
|
||||
if newEnabled {
|
||||
if err := enablePlugin(ctx, d, cl); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := disablePlugin(ctx, d, cl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceDockerPluginUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
ctx := context.Background()
|
||||
if err := pluginUpdate(ctx, d, meta); err != nil {
|
||||
return err
|
||||
}
|
||||
// call the read function to update the resource's state.
|
||||
// https://learn.hashicorp.com/tutorials/terraform/provider-update?in=terraform/providers#implement-update
|
||||
return resourceDockerPluginRead(d, meta)
|
||||
}
|
||||
|
||||
func resourceDockerPluginDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*ProviderConfig).DockerClient
|
||||
ctx := context.Background()
|
||||
pluginID := d.Id()
|
||||
log.Printf("[DEBUG] Remove a Docker plugin " + pluginID)
|
||||
if err := client.PluginRemove(ctx, pluginID, types.PluginRemoveOptions{
|
||||
Force: d.Get("force_destroy").(bool),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("remove the Docker plugin "+pluginID+": %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
414
docker/resource_docker_plugin_test.go
Normal file
414
docker/resource_docker_plugin_test.go
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
package docker
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
|
||||
)
|
||||
|
||||
func Test_getDockerPluginEnv(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := []struct {
|
||||
title string
|
||||
src interface{}
|
||||
exp []string
|
||||
}{
|
||||
{
|
||||
title: "nil",
|
||||
},
|
||||
{
|
||||
title: "basic",
|
||||
src: schema.NewSet(schema.HashString, []interface{}{"DEBUG=1"}),
|
||||
exp: []string{"DEBUG=1"},
|
||||
},
|
||||
}
|
||||
for _, d := range data {
|
||||
d := d
|
||||
t.Run(d.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
envs := getDockerPluginEnv(d.src)
|
||||
if !reflect.DeepEqual(d.exp, envs) {
|
||||
t.Fatalf("want %v, got %v", d.exp, envs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_complementTag(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := []struct {
|
||||
title string
|
||||
image string
|
||||
exp string
|
||||
}{
|
||||
{
|
||||
title: "alpine:3.11.6",
|
||||
image: "alpine:3.11.6",
|
||||
exp: "alpine:3.11.6",
|
||||
},
|
||||
{
|
||||
title: "alpine",
|
||||
image: "alpine",
|
||||
exp: "alpine:latest",
|
||||
},
|
||||
}
|
||||
for _, d := range data {
|
||||
d := d
|
||||
t.Run(d.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
image := complementTag(d.image)
|
||||
if image != d.exp {
|
||||
t.Fatalf("want %v, got %v", d.exp, image)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_normalizePluginName(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := []struct {
|
||||
title string
|
||||
image string
|
||||
isErr bool
|
||||
exp string
|
||||
}{
|
||||
{
|
||||
title: "alpine:3.11.6",
|
||||
image: "alpine:3.11.6",
|
||||
exp: "docker.io/library/alpine:3.11.6",
|
||||
},
|
||||
{
|
||||
title: "alpine",
|
||||
image: "alpine",
|
||||
exp: "docker.io/library/alpine:latest",
|
||||
},
|
||||
{
|
||||
title: "vieux/sshfs",
|
||||
image: "vieux/sshfs",
|
||||
exp: "docker.io/vieux/sshfs:latest",
|
||||
},
|
||||
{
|
||||
title: "docker.io/vieux/sshfs:latest",
|
||||
image: "docker.io/vieux/sshfs:latest",
|
||||
exp: "docker.io/vieux/sshfs:latest",
|
||||
},
|
||||
{
|
||||
title: "docker.io/vieux/sshfs",
|
||||
image: "docker.io/vieux/sshfs",
|
||||
exp: "docker.io/vieux/sshfs:latest",
|
||||
},
|
||||
}
|
||||
for _, d := range data {
|
||||
d := d
|
||||
t.Run(d.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
image, err := normalizePluginName(d.image)
|
||||
if d.isErr {
|
||||
if err == nil {
|
||||
t.Fatal("error should be returned")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if image != d.exp {
|
||||
t.Fatalf("want %v, got %v", d.exp, image)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getDockerPluginGrantPermissions(t *testing.T) {
|
||||
t.Parallel()
|
||||
data := []struct {
|
||||
title string
|
||||
src interface{}
|
||||
privileges types.PluginPrivileges
|
||||
exp bool
|
||||
isErr bool
|
||||
}{
|
||||
{
|
||||
title: "no privilege",
|
||||
src: schema.NewSet(dockerPluginGrantPermissionsSetFunc, []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "network",
|
||||
"value": schema.NewSet(schema.HashString, []interface{}{"host"}),
|
||||
},
|
||||
}),
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
title: "basic",
|
||||
src: schema.NewSet(dockerPluginGrantPermissionsSetFunc, []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "network",
|
||||
"value": schema.NewSet(schema.HashString, []interface{}{"host"}),
|
||||
},
|
||||
}),
|
||||
privileges: types.PluginPrivileges{
|
||||
{
|
||||
Name: "network",
|
||||
Value: []string{"host"},
|
||||
},
|
||||
},
|
||||
exp: true,
|
||||
},
|
||||
{
|
||||
title: "permission denied 1",
|
||||
src: schema.NewSet(dockerPluginGrantPermissionsSetFunc, []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "network",
|
||||
"value": schema.NewSet(schema.HashString, []interface{}{
|
||||
"host",
|
||||
}),
|
||||
},
|
||||
}),
|
||||
privileges: types.PluginPrivileges{
|
||||
{
|
||||
Name: "device",
|
||||
Value: []string{"/dev/fuse"},
|
||||
},
|
||||
},
|
||||
exp: false,
|
||||
},
|
||||
{
|
||||
title: "permission denied 2",
|
||||
src: schema.NewSet(dockerPluginGrantPermissionsSetFunc, []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "network",
|
||||
"value": schema.NewSet(schema.HashString, []interface{}{
|
||||
"host",
|
||||
}),
|
||||
},
|
||||
map[string]interface{}{
|
||||
"name": "mount",
|
||||
"value": schema.NewSet(schema.HashString, []interface{}{
|
||||
"/var/lib/docker/plugins/",
|
||||
}),
|
||||
},
|
||||
}),
|
||||
privileges: types.PluginPrivileges{
|
||||
{
|
||||
Name: "network",
|
||||
Value: []string{"host"},
|
||||
},
|
||||
{
|
||||
Name: "mount",
|
||||
Value: []string{"", "/var/lib/docker/plugins/"},
|
||||
},
|
||||
},
|
||||
exp: false,
|
||||
},
|
||||
}
|
||||
for _, d := range data {
|
||||
d := d
|
||||
t.Run(d.title, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := getDockerPluginGrantPermissions(d.src)
|
||||
b, err := f(d.privileges)
|
||||
if d.isErr {
|
||||
if err == nil {
|
||||
t.Fatal("error must be returned")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(d.exp, b) {
|
||||
t.Fatalf("want %v, got %v", d.exp, b)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAccDockerPlugin_basic(t *testing.T) {
|
||||
const resourceName = "docker_plugin.test"
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
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"),
|
||||
),
|
||||
},
|
||||
{
|
||||
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"),
|
||||
),
|
||||
},
|
||||
{
|
||||
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"),
|
||||
resource.TestCheckResourceAttr(resourceName, "grant_all_permissions", "true"),
|
||||
resource.TestCheckResourceAttr(resourceName, "force_destroy", "true"),
|
||||
resource.TestCheckResourceAttr(resourceName, "enable_timeout", "60"),
|
||||
),
|
||||
},
|
||||
{
|
||||
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"),
|
||||
resource.TestCheckResourceAttr(resourceName, "grant_all_permissions", "true"),
|
||||
resource.TestCheckResourceAttr(resourceName, "force_destroy", "true"),
|
||||
resource.TestCheckResourceAttr(resourceName, "enable_timeout", "60"),
|
||||
resource.TestCheckResourceAttr(resourceName, "force_disable", "true"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccDockerPlugin_grantAllPermissions(t *testing.T) {
|
||||
const resourceName = "docker_plugin.test"
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
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"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccDockerPlugin_grantPermissions(t *testing.T) {
|
||||
const resourceName = "docker_plugin.test"
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
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"),
|
||||
),
|
||||
},
|
||||
{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const testAccDockerPluginMinimum = `
|
||||
resource "docker_plugin" "test" {
|
||||
name = "docker.io/tiborvass/sample-volume-plugin:latest"
|
||||
force_destroy = true
|
||||
}`
|
||||
|
||||
const testAccDockerPluginAlias = `
|
||||
resource "docker_plugin" "test" {
|
||||
name = "docker.io/tiborvass/sample-volume-plugin:latest"
|
||||
alias = "sample:latest"
|
||||
force_destroy = true
|
||||
}`
|
||||
|
||||
const testAccDockerPluginDisableWhenSet = `
|
||||
resource "docker_plugin" "test" {
|
||||
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" {
|
||||
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"
|
||||
]
|
||||
}`
|
||||
|
||||
// To install this plugin, it is required to grant required permissions.
|
||||
const testAccDockerPluginGrantAllPermissions = `
|
||||
resource "docker_plugin" "test" {
|
||||
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" {
|
||||
name = "vieux/sshfs"
|
||||
force_destroy = true
|
||||
grant_permissions {
|
||||
name = "network"
|
||||
value = [
|
||||
"host"
|
||||
]
|
||||
}
|
||||
grant_permissions {
|
||||
name = "mount"
|
||||
value = [
|
||||
"",
|
||||
"/var/lib/docker/plugins/"
|
||||
]
|
||||
}
|
||||
grant_permissions {
|
||||
name = "device"
|
||||
value = [
|
||||
"/dev/fuse"
|
||||
]
|
||||
}
|
||||
grant_permissions {
|
||||
name = "capabilities"
|
||||
value = [
|
||||
"CAP_SYS_ADMIN"
|
||||
]
|
||||
}
|
||||
}`
|
||||
|
|
@ -260,7 +260,7 @@ func resourceDockerService() *schema.Resource {
|
|||
},
|
||||
"driver_name": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Name of the driver to use to create the volume.",
|
||||
Description: "Name of the driver to use to create the volume",
|
||||
Optional: true,
|
||||
},
|
||||
"driver_options": {
|
||||
|
|
@ -354,7 +354,7 @@ func resourceDockerService() *schema.Resource {
|
|||
},
|
||||
"hosts": {
|
||||
Type: schema.TypeSet,
|
||||
Description: "A list of hostname/IP mappings to add to the container's hosts file.",
|
||||
Description: "A list of hostname/IP mappings to add to the container's hosts file",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
|
|
@ -597,7 +597,7 @@ func resourceDockerService() *schema.Resource {
|
|||
},
|
||||
"restart_policy": {
|
||||
Type: schema.TypeMap,
|
||||
Description: "Specification for the restart policy which applies to containers created as part of this service.",
|
||||
Description: "Specification for the restart policy which applies to containers created as part of this service",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
|
|
@ -695,7 +695,7 @@ func resourceDockerService() *schema.Resource {
|
|||
},
|
||||
"networks": {
|
||||
Type: schema.TypeSet,
|
||||
Description: "Ids of the networks in which the container will be put in.",
|
||||
Description: "Ids of the networks in which the container will be put in",
|
||||
Optional: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Set: schema.HashString,
|
||||
|
|
@ -883,7 +883,7 @@ func resourceDockerService() *schema.Resource {
|
|||
},
|
||||
"ports": {
|
||||
Type: schema.TypeList,
|
||||
Description: "List of exposed ports that this service is accessible on from the outside. Ports can only be provided if 'vip' resolution mode is used.",
|
||||
Description: "List of exposed ports that this service is accessible on from the outside. Ports can only be provided if 'vip' resolution mode is used",
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
|
|
@ -906,7 +906,7 @@ func resourceDockerService() *schema.Resource {
|
|||
},
|
||||
"published_port": {
|
||||
Type: schema.TypeInt,
|
||||
Description: "The port on the swarm hosts.",
|
||||
Description: "The port on the swarm hosts",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
|
@ -1205,7 +1205,7 @@ func resourceDockerServiceV0() *schema.Resource {
|
|||
},
|
||||
"driver_name": {
|
||||
Type: schema.TypeString,
|
||||
Description: "Name of the driver to use to create the volume.",
|
||||
Description: "Name of the driver to use to create the volume",
|
||||
Optional: true,
|
||||
},
|
||||
"driver_options": {
|
||||
|
|
@ -1299,7 +1299,7 @@ func resourceDockerServiceV0() *schema.Resource {
|
|||
},
|
||||
"hosts": {
|
||||
Type: schema.TypeSet,
|
||||
Description: "A list of hostname/IP mappings to add to the container's hosts file.",
|
||||
Description: "A list of hostname/IP mappings to add to the container's hosts file",
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
|
|
@ -1504,7 +1504,7 @@ func resourceDockerServiceV0() *schema.Resource {
|
|||
},
|
||||
"restart_policy": {
|
||||
Type: schema.TypeMap,
|
||||
Description: "Specification for the restart policy which applies to containers created as part of this service.",
|
||||
Description: "Specification for the restart policy which applies to containers created as part of this service",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
Elem: &schema.Resource{
|
||||
|
|
@ -1596,7 +1596,7 @@ func resourceDockerServiceV0() *schema.Resource {
|
|||
},
|
||||
"networks": {
|
||||
Type: schema.TypeSet,
|
||||
Description: "Ids of the networks in which the container will be put in.",
|
||||
Description: "Ids of the networks in which the container will be put in",
|
||||
Optional: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
Set: schema.HashString,
|
||||
|
|
@ -1784,7 +1784,7 @@ func resourceDockerServiceV0() *schema.Resource {
|
|||
},
|
||||
"ports": {
|
||||
Type: schema.TypeSet,
|
||||
Description: "List of exposed ports that this service is accessible on from the outside. Ports can only be provided if 'vip' resolution mode is used.",
|
||||
Description: "List of exposed ports that this service is accessible on from the outside. Ports can only be provided if 'vip' resolution mode is used",
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
|
|
@ -1807,7 +1807,7 @@ func resourceDockerServiceV0() *schema.Resource {
|
|||
},
|
||||
"published_port": {
|
||||
Type: schema.TypeInt,
|
||||
Description: "The port on the swarm hosts.",
|
||||
Description: "The port on the swarm hosts",
|
||||
Optional: true,
|
||||
},
|
||||
"publish_mode": {
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -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
|
||||
|
|
|
|||
37
website/docs/d/plugin.html.markdown
Normal file
37
website/docs/d/plugin.html.markdown
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
layout: "docker"
|
||||
page_title: "Docker: docker_plugin"
|
||||
sidebar_current: "docs-docker-datasource-plugin"
|
||||
description: |-
|
||||
Reads the local Docker pluign.
|
||||
---
|
||||
|
||||
# docker\_plugin
|
||||
|
||||
Reads the local Docker plugin. The plugin must be installed locally.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```hcl
|
||||
data "docker_plugin" "sample-volume-plugin" {
|
||||
alias = "sample-volume-plugin:latest"
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `id` - (Optional, string) The Docker plugin ID.
|
||||
* `alias` - (Optional, string) The alias of the Docker plugin.
|
||||
|
||||
One of `id` or `alias` must be assigned.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported in addition to the above configuration:
|
||||
|
||||
* `plugin_reference` - (Optional, string, Forces new resource) The plugin reference.
|
||||
* `disabled` - (Optional, boolean) If true, the plugin is disabled.
|
||||
* `grant_all_permissions` - (Optional, boolean) If true, grant all permissions necessary to run the plugin.
|
||||
* `args` - (Optional, set of string). Currently, only environment variables are supported.
|
||||
|
|
@ -52,7 +52,7 @@ The following arguments are supported:
|
|||
registry when using the `docker_registry_image` [data source](/docs/providers/docker/d/registry_image.html)
|
||||
to trigger an image update.
|
||||
* `pull_trigger` - **Deprecated**, use `pull_triggers` instead.
|
||||
* `force_remove` - (Optional, boolean) If true, then the image is removed Forcely when the resource is destroyed.
|
||||
* `force_remove` - (Optional, boolean) If true, then the image is removed forcibly when the resource is destroyed.
|
||||
* `build` - (Optional, block) See [Build](#build-1) below for details.
|
||||
|
||||
<a id="build-1"></a>
|
||||
|
|
|
|||
102
website/docs/r/plugin.html.markdown
Normal file
102
website/docs/r/plugin.html.markdown
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
layout: "docker"
|
||||
page_title: "Docker: docker_plugin"
|
||||
sidebar_current: "docs-docker-resource-plugin"
|
||||
description: |-
|
||||
Manages the lifecycle of a Docker plugin.
|
||||
---
|
||||
|
||||
# docker\_plugin
|
||||
|
||||
Manages the lifecycle of a Docker plugin.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```hcl
|
||||
resource "docker_plugin" "sample-volume-plugin" {
|
||||
name = "docker.io/tiborvass/sample-volume-plugin:latest"
|
||||
}
|
||||
```
|
||||
|
||||
```hcl
|
||||
resource "docker_plugin" "sample-volume-plugin" {
|
||||
name = "tiborvass/sample-volume-plugin"
|
||||
alias = "sample-volume-plugin"
|
||||
enabled = false
|
||||
grant_all_permissions = true
|
||||
force_destroy = true
|
||||
enable_timeout = 60
|
||||
force_disable = true
|
||||
env = [
|
||||
"DEBUG=1"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `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`.
|
||||
* `grant_permissions` - (Optional, block) grant permissions necessary to run the plugin. This attribute conflicts with `grant_all_permissions`. See [grant_permissions](#grant-permissions-1) below for details.
|
||||
* `env` - (Optional, set of string). The environment variables.
|
||||
* `force_destroy` - (Optional, boolean) If true, the plugin is removed forcibly when the plugin is removed.
|
||||
* `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="grant-permissions-1"></a>
|
||||
## grant_permissions
|
||||
|
||||
`grant_permissions` is a block within the configuration that can be repeated to grant permissions to install the plugin. Each `grant_permissions` block supports
|
||||
the following:
|
||||
|
||||
* `name` - (Required, string)
|
||||
* `value` - (Required, list of string)
|
||||
|
||||
Example:
|
||||
|
||||
```hcl
|
||||
resource "docker_plugin" "sshfs" {
|
||||
name = "docker.io/vieux/sshfs:latest"
|
||||
grant_permissions {
|
||||
name = "network"
|
||||
value = [
|
||||
"host"
|
||||
]
|
||||
}
|
||||
grant_permissions {
|
||||
name = "mount"
|
||||
value = [
|
||||
"",
|
||||
"/var/lib/docker/plugins/"
|
||||
]
|
||||
}
|
||||
grant_permissions {
|
||||
name = "device"
|
||||
value = [
|
||||
"/dev/fuse"
|
||||
]
|
||||
}
|
||||
grant_permissions {
|
||||
name = "capabilities"
|
||||
value = [
|
||||
"CAP_SYS_ADMIN"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 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`:
|
||||
|
||||
```sh
|
||||
$ terraform import docker_plugin.sample-volume-plugin $(docker plugin inspect -f "{{.ID}}" tiborvass/sample-volume-plugin:latest)
|
||||
```
|
||||
Loading…
Reference in a new issue