2016-12-05 16:29:41 +01:00
|
|
|
package rancher
|
|
|
|
|
|
|
|
import (
|
2017-06-08 11:24:53 +02:00
|
|
|
"encoding/json"
|
2016-12-05 16:29:41 +01:00
|
|
|
"fmt"
|
|
|
|
"log"
|
2017-06-08 11:24:53 +02:00
|
|
|
"net/http"
|
2017-03-14 18:08:23 +01:00
|
|
|
"reflect"
|
2016-12-05 16:29:41 +01:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2017-03-14 18:08:23 +01:00
|
|
|
compose "github.com/docker/libcompose/config"
|
2016-12-05 16:29:41 +01:00
|
|
|
"github.com/hashicorp/terraform/helper/resource"
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
"github.com/hashicorp/terraform/helper/validation"
|
2017-06-08 11:24:53 +02:00
|
|
|
"github.com/rancher/go-rancher/catalog"
|
|
|
|
rancherClient "github.com/rancher/go-rancher/v2"
|
2016-12-05 16:29:41 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
func resourceRancherStack() *schema.Resource {
|
|
|
|
return &schema.Resource{
|
|
|
|
Create: resourceRancherStackCreate,
|
|
|
|
Read: resourceRancherStackRead,
|
|
|
|
Update: resourceRancherStackUpdate,
|
|
|
|
Delete: resourceRancherStackDelete,
|
|
|
|
Importer: &schema.ResourceImporter{
|
2017-02-03 13:34:26 +01:00
|
|
|
State: resourceRancherStackImport,
|
2016-12-05 16:29:41 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
|
|
"id": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"name": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
},
|
|
|
|
"description": &schema.Schema{
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"environment_id": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Required: true,
|
|
|
|
ForceNew: true,
|
|
|
|
},
|
|
|
|
"docker_compose": {
|
2017-03-14 18:08:23 +01:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
DiffSuppressFunc: suppressComposeDiff,
|
2016-12-05 16:29:41 +01:00
|
|
|
},
|
|
|
|
"rancher_compose": {
|
2017-03-14 18:08:23 +01:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
DiffSuppressFunc: suppressComposeDiff,
|
2016-12-05 16:29:41 +01:00
|
|
|
},
|
|
|
|
"environment": {
|
|
|
|
Type: schema.TypeMap,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"catalog_id": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"scope": {
|
|
|
|
Type: schema.TypeString,
|
|
|
|
Default: "user",
|
|
|
|
Optional: true,
|
|
|
|
ValidateFunc: validation.StringInSlice([]string{"user", "system"}, true),
|
|
|
|
},
|
|
|
|
"start_on_create": {
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Optional: true,
|
|
|
|
Computed: true,
|
|
|
|
},
|
|
|
|
"finish_upgrade": {
|
|
|
|
Type: schema.TypeBool,
|
|
|
|
Optional: true,
|
|
|
|
},
|
|
|
|
"rendered_docker_compose": {
|
2017-04-23 12:41:18 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
2016-12-05 16:29:41 +01:00
|
|
|
},
|
|
|
|
"rendered_rancher_compose": {
|
2017-04-23 12:41:18 +02:00
|
|
|
Type: schema.TypeString,
|
|
|
|
Computed: true,
|
2016-12-05 16:29:41 +01:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceRancherStackCreate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
log.Printf("[INFO] Creating Stack: %s", d.Id())
|
|
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := makeStackData(d, meta)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
var newStack rancherClient.Stack
|
|
|
|
if err := client.Create("stack", data, &newStack); err != nil {
|
2016-12-05 16:29:41 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
stateConf := &resource.StateChangeConf{
|
|
|
|
Pending: []string{"activating", "active", "removed", "removing"},
|
|
|
|
Target: []string{"active"},
|
|
|
|
Refresh: StackStateRefreshFunc(client, newStack.Id),
|
|
|
|
Timeout: 10 * time.Minute,
|
|
|
|
Delay: 1 * time.Second,
|
|
|
|
MinTimeout: 3 * time.Second,
|
|
|
|
}
|
|
|
|
_, waitErr := stateConf.WaitForState()
|
|
|
|
if waitErr != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"Error waiting for stack (%s) to be created: %s", newStack.Id, waitErr)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId(newStack.Id)
|
|
|
|
log.Printf("[INFO] Stack ID: %s", d.Id())
|
|
|
|
|
|
|
|
return resourceRancherStackRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceRancherStackRead(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
log.Printf("[INFO] Refreshing Stack: %s", d.Id())
|
2017-01-30 18:08:21 +01:00
|
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-12-05 16:29:41 +01:00
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
stack, err := client.Stack.ById(d.Id())
|
2016-12-05 16:29:41 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-01-31 14:04:59 +01:00
|
|
|
if stack == nil {
|
|
|
|
log.Printf("[INFO] Stack %s not found", d.Id())
|
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-02-01 20:49:17 +01:00
|
|
|
if removed(stack.State) {
|
2017-01-31 10:58:16 +01:00
|
|
|
log.Printf("[INFO] Stack %s was removed on %v", d.Id(), stack.Removed)
|
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
config, err := client.Stack.ActionExportconfig(stack, &rancherClient.ComposeConfigInput{})
|
2016-12-05 16:29:41 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[INFO] Stack Name: %s", stack.Name)
|
|
|
|
|
|
|
|
d.Set("description", stack.Description)
|
|
|
|
d.Set("name", stack.Name)
|
2017-01-31 16:57:35 +01:00
|
|
|
dockerCompose := strings.Replace(config.DockerComposeConfig, "\r", "", -1)
|
|
|
|
rancherCompose := strings.Replace(config.RancherComposeConfig, "\r", "", -1)
|
2017-02-01 13:33:23 +01:00
|
|
|
|
2017-02-05 11:35:48 +01:00
|
|
|
catalogID := d.Get("catalog_id")
|
|
|
|
if catalogID == "" {
|
2017-02-01 13:33:23 +01:00
|
|
|
d.Set("docker_compose", dockerCompose)
|
|
|
|
d.Set("rancher_compose", rancherCompose)
|
2017-02-05 11:35:48 +01:00
|
|
|
} else {
|
|
|
|
d.Set("docker_compose", "")
|
|
|
|
d.Set("rancher_compose", "")
|
2017-02-01 13:33:23 +01:00
|
|
|
}
|
2017-01-31 16:57:35 +01:00
|
|
|
d.Set("rendered_docker_compose", dockerCompose)
|
|
|
|
d.Set("rendered_rancher_compose", rancherCompose)
|
2016-12-05 16:29:41 +01:00
|
|
|
d.Set("environment_id", stack.AccountId)
|
|
|
|
d.Set("environment", stack.Environment)
|
|
|
|
|
|
|
|
if stack.ExternalId == "" {
|
|
|
|
d.Set("scope", "user")
|
|
|
|
d.Set("catalog_id", "")
|
|
|
|
} else {
|
|
|
|
trimmedID := strings.TrimPrefix(stack.ExternalId, "system-")
|
|
|
|
if trimmedID == stack.ExternalId {
|
|
|
|
d.Set("scope", "user")
|
|
|
|
} else {
|
|
|
|
d.Set("scope", "system")
|
|
|
|
}
|
|
|
|
d.Set("catalog_id", strings.TrimPrefix(trimmedID, "catalog://"))
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Set("start_on_create", stack.StartOnCreate)
|
2017-03-09 00:32:28 +01:00
|
|
|
d.Set("finish_upgrade", d.Get("finish_upgrade").(bool))
|
2016-12-05 16:29:41 +01:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceRancherStackUpdate(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
log.Printf("[INFO] Updating Stack: %s", d.Id())
|
|
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
d.Partial(true)
|
|
|
|
|
|
|
|
data, err := makeStackData(d, meta)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
stack, err := client.Stack.ById(d.Id())
|
2016-12-05 16:29:41 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
var newStack rancherClient.Stack
|
|
|
|
if err = client.Update(stack.Type, &stack.Resource, data, &newStack); err != nil {
|
2016-12-05 16:29:41 +01:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
stateConf := &resource.StateChangeConf{
|
|
|
|
Pending: []string{"active", "active-updating"},
|
|
|
|
Target: []string{"active"},
|
|
|
|
Refresh: StackStateRefreshFunc(client, newStack.Id),
|
|
|
|
Timeout: 10 * time.Minute,
|
|
|
|
Delay: 1 * time.Second,
|
|
|
|
MinTimeout: 3 * time.Second,
|
|
|
|
}
|
|
|
|
s, waitErr := stateConf.WaitForState()
|
2017-06-08 11:24:53 +02:00
|
|
|
stack = s.(*rancherClient.Stack)
|
2016-12-05 16:29:41 +01:00
|
|
|
if waitErr != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"Error waiting for stack (%s) to be updated: %s", stack.Id, waitErr)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetPartial("name")
|
|
|
|
d.SetPartial("description")
|
|
|
|
d.SetPartial("scope")
|
|
|
|
|
|
|
|
if d.HasChange("docker_compose") ||
|
|
|
|
d.HasChange("rancher_compose") ||
|
|
|
|
d.HasChange("environment") ||
|
|
|
|
d.HasChange("catalog_id") {
|
|
|
|
|
|
|
|
envMap := make(map[string]interface{})
|
|
|
|
for key, value := range *data["environment"].(*map[string]string) {
|
|
|
|
envValue := value
|
|
|
|
envMap[key] = &envValue
|
|
|
|
}
|
2017-06-08 11:24:53 +02:00
|
|
|
stack, err = client.Stack.ActionUpgrade(stack, &rancherClient.StackUpgrade{
|
2016-12-05 16:29:41 +01:00
|
|
|
DockerCompose: *data["dockerCompose"].(*string),
|
|
|
|
RancherCompose: *data["rancherCompose"].(*string),
|
|
|
|
Environment: envMap,
|
|
|
|
ExternalId: *data["externalId"].(*string),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
stateConf := &resource.StateChangeConf{
|
|
|
|
Pending: []string{"active", "upgrading", "upgraded"},
|
|
|
|
Target: []string{"upgraded"},
|
|
|
|
Refresh: StackStateRefreshFunc(client, stack.Id),
|
|
|
|
Timeout: 10 * time.Minute,
|
|
|
|
Delay: 1 * time.Second,
|
|
|
|
MinTimeout: 3 * time.Second,
|
|
|
|
}
|
|
|
|
s, waitErr := stateConf.WaitForState()
|
|
|
|
if waitErr != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"Error waiting for stack (%s) to be upgraded: %s", stack.Id, waitErr)
|
|
|
|
}
|
2017-06-08 11:24:53 +02:00
|
|
|
stack = s.(*rancherClient.Stack)
|
2016-12-05 16:29:41 +01:00
|
|
|
|
|
|
|
if d.Get("finish_upgrade").(bool) {
|
2017-06-08 11:24:53 +02:00
|
|
|
stack, err = client.Stack.ActionFinishupgrade(stack)
|
2016-12-05 16:29:41 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
stateConf = &resource.StateChangeConf{
|
2017-01-04 10:16:04 +01:00
|
|
|
Pending: []string{"active", "upgraded", "finishing-upgrade"},
|
2016-12-05 16:29:41 +01:00
|
|
|
Target: []string{"active"},
|
|
|
|
Refresh: StackStateRefreshFunc(client, stack.Id),
|
|
|
|
Timeout: 10 * time.Minute,
|
|
|
|
Delay: 1 * time.Second,
|
|
|
|
MinTimeout: 3 * time.Second,
|
|
|
|
}
|
|
|
|
_, waitErr = stateConf.WaitForState()
|
|
|
|
if waitErr != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"Error waiting for stack (%s) to be upgraded: %s", stack.Id, waitErr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetPartial("rendered_docker_compose")
|
|
|
|
d.SetPartial("rendered_rancher_compose")
|
|
|
|
d.SetPartial("docker_compose")
|
|
|
|
d.SetPartial("rancher_compose")
|
|
|
|
d.SetPartial("environment")
|
|
|
|
d.SetPartial("catalog_id")
|
|
|
|
}
|
|
|
|
|
|
|
|
d.Partial(false)
|
|
|
|
|
|
|
|
return resourceRancherStackRead(d, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
func resourceRancherStackDelete(d *schema.ResourceData, meta interface{}) error {
|
|
|
|
log.Printf("[INFO] Deleting Stack: %s", d.Id())
|
|
|
|
id := d.Id()
|
|
|
|
client, err := meta.(*Config).EnvironmentClient(d.Get("environment_id").(string))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
stack, err := client.Stack.ById(id)
|
2016-12-05 16:29:41 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
if err := client.Stack.Delete(stack); err != nil {
|
2016-12-05 16:29:41 +01:00
|
|
|
return fmt.Errorf("Error deleting Stack: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Printf("[DEBUG] Waiting for stack (%s) to be removed", id)
|
|
|
|
|
|
|
|
stateConf := &resource.StateChangeConf{
|
|
|
|
Pending: []string{"active", "removed", "removing"},
|
|
|
|
Target: []string{"removed"},
|
|
|
|
Refresh: StackStateRefreshFunc(client, id),
|
|
|
|
Timeout: 10 * time.Minute,
|
|
|
|
Delay: 1 * time.Second,
|
|
|
|
MinTimeout: 3 * time.Second,
|
|
|
|
}
|
|
|
|
|
|
|
|
_, waitErr := stateConf.WaitForState()
|
|
|
|
if waitErr != nil {
|
|
|
|
return fmt.Errorf(
|
|
|
|
"Error waiting for stack (%s) to be removed: %s", id, waitErr)
|
|
|
|
}
|
|
|
|
|
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-02-03 13:34:26 +01:00
|
|
|
func resourceRancherStackImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
2017-02-05 11:35:48 +01:00
|
|
|
envID, resourceID := splitID(d.Id())
|
|
|
|
d.SetId(resourceID)
|
|
|
|
if envID != "" {
|
|
|
|
d.Set("environment_id", envID)
|
|
|
|
} else {
|
|
|
|
client, err := meta.(*Config).GlobalClient()
|
|
|
|
if err != nil {
|
|
|
|
return []*schema.ResourceData{}, err
|
|
|
|
}
|
2017-06-08 11:24:53 +02:00
|
|
|
stack, err := client.Stack.ById(d.Id())
|
2017-02-05 11:35:48 +01:00
|
|
|
if err != nil {
|
|
|
|
return []*schema.ResourceData{}, err
|
|
|
|
}
|
|
|
|
d.Set("environment_id", stack.AccountId)
|
2017-02-03 13:34:26 +01:00
|
|
|
}
|
|
|
|
return []*schema.ResourceData{d}, nil
|
|
|
|
}
|
|
|
|
|
2016-12-05 16:29:41 +01:00
|
|
|
// StackStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
|
|
|
|
// a Rancher Stack.
|
|
|
|
func StackStateRefreshFunc(client *rancherClient.RancherClient, stackID string) resource.StateRefreshFunc {
|
|
|
|
return func() (interface{}, string, error) {
|
2017-06-08 11:24:53 +02:00
|
|
|
stack, err := client.Stack.ById(stackID)
|
2016-12-05 16:29:41 +01:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return stack, stack.State, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func environmentFromMap(m map[string]interface{}) map[string]string {
|
|
|
|
result := make(map[string]string)
|
|
|
|
for k, v := range m {
|
|
|
|
result[k] = v.(string)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
func makeStackData(d *schema.ResourceData, meta interface{}) (data map[string]interface{}, err error) {
|
|
|
|
name := d.Get("name").(string)
|
|
|
|
description := d.Get("description").(string)
|
|
|
|
|
|
|
|
var externalID string
|
|
|
|
var dockerCompose string
|
|
|
|
var rancherCompose string
|
|
|
|
var environment map[string]string
|
|
|
|
if c, ok := d.GetOk("catalog_id"); ok {
|
|
|
|
if scope, ok := d.GetOk("scope"); ok && scope.(string) == "system" {
|
|
|
|
externalID = "system-"
|
|
|
|
}
|
|
|
|
catalogID := c.(string)
|
|
|
|
externalID += "catalog://" + catalogID
|
|
|
|
|
|
|
|
catalogClient, err := meta.(*Config).CatalogClient()
|
|
|
|
if err != nil {
|
|
|
|
return data, err
|
|
|
|
}
|
2017-06-08 11:24:53 +02:00
|
|
|
|
|
|
|
templateVersion, err := getCatalogTemplateVersion(catalogClient, catalogID)
|
2016-12-05 16:29:41 +01:00
|
|
|
if err != nil {
|
2017-06-08 11:24:53 +02:00
|
|
|
return data, err
|
2016-12-05 16:29:41 +01:00
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
if templateVersion.Id != catalogID {
|
|
|
|
return data, fmt.Errorf("Did not find template %s", catalogID)
|
2017-01-31 14:04:24 +01:00
|
|
|
}
|
|
|
|
|
2017-06-08 11:24:53 +02:00
|
|
|
dockerCompose = templateVersion.Files["docker-compose.yml"].(string)
|
|
|
|
rancherCompose = templateVersion.Files["rancher-compose.yml"].(string)
|
2016-12-05 16:29:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if c, ok := d.GetOk("docker_compose"); ok {
|
|
|
|
dockerCompose = c.(string)
|
|
|
|
}
|
|
|
|
if c, ok := d.GetOk("rancher_compose"); ok {
|
|
|
|
rancherCompose = c.(string)
|
|
|
|
}
|
2017-06-08 11:24:53 +02:00
|
|
|
|
2016-12-05 16:29:41 +01:00
|
|
|
environment = environmentFromMap(d.Get("environment").(map[string]interface{}))
|
|
|
|
|
|
|
|
startOnCreate := d.Get("start_on_create")
|
2017-06-08 11:24:53 +02:00
|
|
|
system := systemScope(d.Get("scope").(string))
|
2016-12-05 16:29:41 +01:00
|
|
|
|
|
|
|
data = map[string]interface{}{
|
|
|
|
"name": &name,
|
|
|
|
"description": &description,
|
|
|
|
"dockerCompose": &dockerCompose,
|
|
|
|
"rancherCompose": &rancherCompose,
|
|
|
|
"environment": &environment,
|
|
|
|
"externalId": &externalID,
|
|
|
|
"startOnCreate": &startOnCreate,
|
2017-06-08 11:24:53 +02:00
|
|
|
"system": &system,
|
2016-12-05 16:29:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
}
|
2017-03-14 18:08:23 +01:00
|
|
|
|
|
|
|
func suppressComposeDiff(k, old, new string, d *schema.ResourceData) bool {
|
|
|
|
cOld, err := compose.CreateConfig([]byte(old))
|
|
|
|
if err != nil {
|
|
|
|
// TODO: log?
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
cNew, err := compose.CreateConfig([]byte(new))
|
|
|
|
if err != nil {
|
|
|
|
// TODO: log?
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return reflect.DeepEqual(cOld, cNew)
|
|
|
|
}
|
2017-06-08 11:24:53 +02:00
|
|
|
|
|
|
|
func getCatalogTemplateVersion(c *catalog.RancherClient, catalogID string) (*catalog.TemplateVersion, error) {
|
|
|
|
templateVersion := &catalog.TemplateVersion{}
|
|
|
|
|
|
|
|
namesAndFolder := strings.SplitN(catalogID, ":", 3)
|
|
|
|
if len(namesAndFolder) != 3 {
|
|
|
|
return templateVersion, fmt.Errorf("catalog_id: %s not in 'catalog:name:N' format", catalogID)
|
|
|
|
}
|
|
|
|
|
|
|
|
template, err := c.Template.ById(namesAndFolder[0] + ":" + namesAndFolder[1])
|
|
|
|
if err != nil {
|
|
|
|
return templateVersion, fmt.Errorf("Failed to get catalog template: %s at url %s", err, c.GetOpts().Url)
|
|
|
|
}
|
|
|
|
|
|
|
|
if template == nil {
|
|
|
|
return templateVersion, fmt.Errorf("Unknown catalog template %s", catalogID)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, versionLink := range template.VersionLinks {
|
|
|
|
if strings.HasSuffix(versionLink.(string), catalogID) {
|
|
|
|
client := &http.Client{}
|
|
|
|
req, err := http.NewRequest("GET", fmt.Sprint(versionLink), nil)
|
|
|
|
req.SetBasicAuth(c.GetOpts().AccessKey, c.GetOpts().SecretKey)
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
return templateVersion, err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
if resp.StatusCode != 200 {
|
|
|
|
return templateVersion, fmt.Errorf("Bad Response %d lookup up %s", resp.StatusCode, versionLink)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = json.NewDecoder(resp.Body).Decode(templateVersion)
|
|
|
|
return templateVersion, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return templateVersion, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func systemScope(scope string) bool {
|
|
|
|
return scope == "system"
|
|
|
|
}
|