terraform-provider-docker/internal/provider/resource_docker_secret.go

137 lines
3.6 KiB
Go
Raw Normal View History

package provider
import (
"context"
"encoding/base64"
"log"
"github.com/docker/docker/api/types/swarm"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func resourceDockerSecret() *schema.Resource {
return &schema.Resource{
CreateContext: resourceDockerSecretCreate,
ReadContext: resourceDockerSecretRead,
DeleteContext: resourceDockerSecretDelete,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "User-defined name of the secret",
Required: true,
ForceNew: true,
},
"data": {
Type: schema.TypeString,
Description: "Base64-url-safe-encoded secret data",
Required: true,
Sensitive: true,
ForceNew: true,
ValidateDiagFunc: validateStringIsBase64Encoded(),
},
"labels": {
2019-11-08 18:24:50 -05:00
Type: schema.TypeSet,
2019-11-08 18:56:55 -05:00
Optional: true,
ForceNew: true,
2019-11-08 18:24:50 -05:00
Elem: labelSchema,
},
},
2019-11-12 17:41:59 -05:00
SchemaVersion: 1,
StateUpgraders: []schema.StateUpgrader{
{
Version: 0,
Type: resourceDockerSecretV0().CoreConfigSchema().ImpliedType(),
Upgrade: func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) {
return replaceLabelsMapFieldWithSetField(rawState), nil
2019-11-12 17:41:59 -05:00
},
},
},
}
}
func resourceDockerSecretV0() *schema.Resource {
return &schema.Resource{
// This is only used for state migration, so the CRUD
// callbacks are no longer relevant
2019-11-12 17:41:59 -05:00
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "User-defined name of the secret",
Required: true,
ForceNew: true,
},
"data": {
Type: schema.TypeString,
Description: "User-defined name of the secret",
Required: true,
Sensitive: true,
ForceNew: true,
ValidateDiagFunc: validateStringIsBase64Encoded(),
2019-11-12 17:41:59 -05:00
},
"labels": {
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
},
},
}
}
func resourceDockerSecretCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*ProviderConfig).DockerClient
data, _ := base64.StdEncoding.DecodeString(d.Get("data").(string))
secretSpec := swarm.SecretSpec{
Annotations: swarm.Annotations{
Name: d.Get("name").(string),
},
Data: data,
}
if v, ok := d.GetOk("labels"); ok {
2019-11-08 18:24:50 -05:00
secretSpec.Annotations.Labels = labelSetToMap(v.(*schema.Set))
}
secret, err := client.SecretCreate(ctx, secretSpec)
if err != nil {
return diag.FromErr(err)
}
d.SetId(secret.ID)
return resourceDockerSecretRead(ctx, d, meta)
}
func resourceDockerSecretRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*ProviderConfig).DockerClient
secret, _, err := client.SecretInspectWithRaw(ctx, d.Id())
if err != nil {
log.Printf("[WARN] Secret (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}
d.SetId(secret.ID)
d.Set("name", secret.Spec.Name)
// Note mavogel: secret data is not exposed via the API
// TODO next major if we do not explicitly do not store it in the state we could import it, but BC
// d.Set("data", base64.StdEncoding.EncodeToString(secret.Spec.Data))
return nil
}
func resourceDockerSecretDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*ProviderConfig).DockerClient
err := client.SecretRemove(ctx, d.Id())
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}