mirror of
https://github.com/kreuzwerker/terraform-provider-docker.git
synced 2025-12-22 15:49:34 -05:00
Adds docker swarm features to the provider for the Docker Engine 17.09.1 and API Version 1.32. The spec is close to the API. By default, the swarm services are fire and forget. A converging config implements the features of the docker cli to ensure a service and all its replicas are up and running. Furthermore, service can have configs, secrets, networks, mounts and be added to a network.
201 lines
6 KiB
Go
201 lines
6 KiB
Go
package docker
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/user"
|
|
"strings"
|
|
|
|
dc "github.com/fsouza/go-dockerclient"
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
)
|
|
|
|
// Provider creates the Docker provider
|
|
func Provider() terraform.ResourceProvider {
|
|
return &schema.Provider{
|
|
Schema: map[string]*schema.Schema{
|
|
"host": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_HOST", "unix:///var/run/docker.sock"),
|
|
Description: "The Docker daemon address",
|
|
},
|
|
|
|
"ca_material": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_CA_MATERIAL", ""),
|
|
Description: "PEM-encoded content of Docker host CA certificate",
|
|
},
|
|
"cert_material": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_CERT_MATERIAL", ""),
|
|
Description: "PEM-encoded content of Docker client certificate",
|
|
},
|
|
"key_material": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_KEY_MATERIAL", ""),
|
|
Description: "PEM-encoded content of Docker client private key",
|
|
},
|
|
|
|
"cert_path": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_CERT_PATH", ""),
|
|
Description: "Path to directory with Docker TLS config",
|
|
},
|
|
|
|
"registry_auth": &schema.Schema{
|
|
Type: schema.TypeSet,
|
|
Optional: true,
|
|
Elem: &schema.Resource{
|
|
Schema: map[string]*schema.Schema{
|
|
"address": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
Description: "Address of the registry",
|
|
},
|
|
|
|
"username": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ConflictsWith: []string{"registry_auth.config_file"},
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_REGISTRY_USER", ""),
|
|
Description: "Username for the registry",
|
|
},
|
|
|
|
"password": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Sensitive: true,
|
|
ConflictsWith: []string{"registry_auth.config_file"},
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_REGISTRY_PASS", ""),
|
|
Description: "Password for the registry",
|
|
},
|
|
|
|
"config_file": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ConflictsWith: []string{"registry_auth.username", "registry_auth.password"},
|
|
DefaultFunc: schema.EnvDefaultFunc("DOCKER_CONFIG", "~/.docker/config.json"),
|
|
Description: "Path to docker json file for registry auth",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
ResourcesMap: map[string]*schema.Resource{
|
|
"docker_container": resourceDockerContainer(),
|
|
"docker_image": resourceDockerImage(),
|
|
"docker_network": resourceDockerNetwork(),
|
|
"docker_volume": resourceDockerVolume(),
|
|
"docker_config": resourceDockerConfig(),
|
|
"docker_secret": resourceDockerSecret(),
|
|
"docker_service": resourceDockerService(),
|
|
},
|
|
|
|
DataSourcesMap: map[string]*schema.Resource{
|
|
"docker_registry_image": dataSourceDockerRegistryImage(),
|
|
},
|
|
|
|
ConfigureFunc: providerConfigure,
|
|
}
|
|
}
|
|
|
|
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
|
config := DockerConfig{
|
|
Host: d.Get("host").(string),
|
|
Ca: d.Get("ca_material").(string),
|
|
Cert: d.Get("cert_material").(string),
|
|
Key: d.Get("key_material").(string),
|
|
CertPath: d.Get("cert_path").(string),
|
|
}
|
|
|
|
client, err := config.NewClient()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error initializing Docker client: %s", err)
|
|
}
|
|
|
|
err = client.Ping()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error pinging Docker server: %s", err)
|
|
}
|
|
|
|
authConfigs := &dc.AuthConfigurations{}
|
|
|
|
if v, ok := d.GetOk("registry_auth"); ok {
|
|
authConfigs, err = providerSetToRegistryAuth(v.(*schema.Set))
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error loading registry auth config: %s", err)
|
|
}
|
|
}
|
|
|
|
providerConfig := ProviderConfig{
|
|
DockerClient: client,
|
|
AuthConfigs: authConfigs,
|
|
}
|
|
|
|
return &providerConfig, nil
|
|
}
|
|
|
|
// Take the given registry_auth schemas and return a map of registry auth configurations
|
|
func providerSetToRegistryAuth(authSet *schema.Set) (*dc.AuthConfigurations, error) {
|
|
authConfigs := dc.AuthConfigurations{
|
|
Configs: make(map[string]dc.AuthConfiguration),
|
|
}
|
|
|
|
for _, authInt := range authSet.List() {
|
|
auth := authInt.(map[string]interface{})
|
|
authConfig := dc.AuthConfiguration{}
|
|
authConfig.ServerAddress = normalizeRegistryAddress(auth["address"].(string))
|
|
|
|
// For each registry_auth block, generate an AuthConfiguration using either
|
|
// username/password or the given config file
|
|
if username, ok := auth["username"]; ok && username.(string) != "" {
|
|
authConfig.Username = auth["username"].(string)
|
|
authConfig.Password = auth["password"].(string)
|
|
} else if configFile, ok := auth["config_file"]; ok && configFile.(string) != "" {
|
|
filePath := configFile.(string)
|
|
if strings.HasPrefix(filePath, "~/") {
|
|
usr, err := user.Current()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
filePath = strings.Replace(filePath, "~", usr.HomeDir, 1)
|
|
}
|
|
|
|
r, err := os.Open(filePath)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error opening docker registry config file: %v", err)
|
|
}
|
|
|
|
auths, err := dc.NewAuthConfigurations(r)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Error parsing docker registry config json: %v", err)
|
|
}
|
|
|
|
foundRegistry := false
|
|
for registry, authFileConfig := range auths.Configs {
|
|
if authConfig.ServerAddress == normalizeRegistryAddress(registry) {
|
|
authConfig.Username = authFileConfig.Username
|
|
authConfig.Password = authFileConfig.Password
|
|
foundRegistry = true
|
|
}
|
|
}
|
|
|
|
if !foundRegistry {
|
|
return nil, fmt.Errorf("Couldn't find registry config for '%s' in file: %s",
|
|
authConfig.ServerAddress, filePath)
|
|
}
|
|
}
|
|
|
|
authConfigs.Configs[authConfig.ServerAddress] = authConfig
|
|
}
|
|
|
|
return &authConfigs, nil
|
|
}
|