github.com/gophercloud/gophercloud@v1.11.0/internal/acceptance/openstack/orchestration/v1/orchestration.go (about)

     1  package v1
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/gophercloud/gophercloud"
     8  	"github.com/gophercloud/gophercloud/internal/acceptance/tools"
     9  	"github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacks"
    10  	th "github.com/gophercloud/gophercloud/testhelper"
    11  )
    12  
    13  const basicTemplateResourceName = "secgroup_1"
    14  const basicTemplate = `
    15  	{
    16  		"heat_template_version": "2013-05-23",
    17  		"description": "Simple template to test heat commands",
    18  		"resources": {
    19  			"secgroup_1": {
    20  				"type": "OS::Neutron::SecurityGroup",
    21  				"properties": {
    22  					"description": "Gophercloud test",
    23  					"name": "secgroup_1"
    24  				}
    25  			}
    26  		}
    27  	}
    28  `
    29  
    30  const validateTemplate = `
    31  	{
    32  		"heat_template_version": "2013-05-23",
    33  		"description": "Simple template to test heat commands",
    34  		"parameters": {
    35  			"flavor": {
    36  				"default": "m1.tiny",
    37  				"type":    "string"
    38  			}
    39  		},
    40  		"resources": {
    41  			"hello_world": {
    42  				"type": "OS::Nova::Server",
    43  				"properties": {
    44  					"key_name": "heat_key",
    45  					"flavor": {
    46  						"get_param": "flavor"
    47  					},
    48  					"image":     "ad091b52-742f-469e-8f3c-fd81cadf0743",
    49  					"user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
    50  				}
    51  			}
    52  		}
    53  	}
    54  `
    55  
    56  // CreateStack will create a heat stack with a randomly generated name.
    57  // An error will be returned if the stack failed to be created.
    58  func CreateStack(t *testing.T, client *gophercloud.ServiceClient) (*stacks.RetrievedStack, error) {
    59  	stackName := tools.RandomString("ACCPTEST", 8)
    60  	t.Logf("Attempting to create stack %s", stackName)
    61  
    62  	template := new(stacks.Template)
    63  	template.Bin = []byte(basicTemplate)
    64  
    65  	createOpts := stacks.CreateOpts{
    66  		Name:            stackName,
    67  		Timeout:         60,
    68  		TemplateOpts:    template,
    69  		DisableRollback: gophercloud.Disabled,
    70  	}
    71  
    72  	stack, err := stacks.Create(client, createOpts).Extract()
    73  	th.AssertNoErr(t, err)
    74  
    75  	if err := WaitForStackStatus(client, stackName, stack.ID, "CREATE_COMPLETE"); err != nil {
    76  		return nil, err
    77  	}
    78  
    79  	newStack, err := stacks.Get(client, stackName, stack.ID).Extract()
    80  	return newStack, err
    81  }
    82  
    83  // DeleteStack deletes a stack via its ID.
    84  // A fatal error will occur if the stack failed to be deleted. This works
    85  // best when used as a deferred function.
    86  func DeleteStack(t *testing.T, client *gophercloud.ServiceClient, stackName, stackID string) {
    87  	t.Logf("Attempting to delete stack %s (%s)", stackName, stackID)
    88  
    89  	err := stacks.Delete(client, stackName, stackID).ExtractErr()
    90  	if err != nil {
    91  		t.Fatalf("Failed to delete stack %s: %s", stackID, err)
    92  	}
    93  
    94  	t.Logf("Deleted stack: %s", stackID)
    95  }
    96  
    97  // WaitForStackStatus will wait until a stack has reached a certain status.
    98  func WaitForStackStatus(client *gophercloud.ServiceClient, stackName, stackID, status string) error {
    99  	return tools.WaitFor(func() (bool, error) {
   100  		latest, err := stacks.Get(client, stackName, stackID).Extract()
   101  		if err != nil {
   102  			return false, err
   103  		}
   104  
   105  		if latest.Status == status {
   106  			return true, nil
   107  		}
   108  
   109  		if latest.Status == "ERROR" {
   110  			return false, fmt.Errorf("Stack in ERROR state")
   111  		}
   112  
   113  		return false, nil
   114  	})
   115  }
   116  
   117  // CreateStackWithFile will create a heat stack with a randomly generated name that uses get_file.
   118  // An error will be returned if the stack failed to be created.
   119  func CreateStackWithFile(t *testing.T, client *gophercloud.ServiceClient) (*stacks.RetrievedStack, error) {
   120  	stackName := tools.RandomString("ACCPTEST", 8)
   121  	t.Logf("Attempting to create stack %s", stackName)
   122  
   123  	template := new(stacks.Template)
   124  	template.Bin = []byte(`heat_template_version: 2015-04-30
   125  resources:
   126    test_resource:
   127      type: OS::Heat::TestResource
   128      properties:
   129        value:
   130          get_file: testdata/samplefile`)
   131  	createOpts := stacks.CreateOpts{
   132  		Name:            stackName,
   133  		Timeout:         1,
   134  		TemplateOpts:    template,
   135  		DisableRollback: gophercloud.Disabled,
   136  	}
   137  
   138  	stack, err := stacks.Create(client, createOpts).Extract()
   139  	th.AssertNoErr(t, err)
   140  
   141  	if err := WaitForStackStatus(client, stackName, stack.ID, "CREATE_COMPLETE"); err != nil {
   142  		return nil, err
   143  	}
   144  
   145  	newStack, err := stacks.Get(client, stackName, stack.ID).Extract()
   146  	return newStack, err
   147  }