1package v1
2
3import (
4	"fmt"
5	"strings"
6	"testing"
7
8	"github.com/gophercloud/gophercloud"
9	"github.com/gophercloud/gophercloud/acceptance/clients"
10	idv3 "github.com/gophercloud/gophercloud/acceptance/openstack/identity/v3"
11	"github.com/gophercloud/gophercloud/acceptance/tools"
12	"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clusters"
13	"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/clustertemplates"
14	"github.com/gophercloud/gophercloud/openstack/containerinfra/v1/quotas"
15	th "github.com/gophercloud/gophercloud/testhelper"
16)
17
18// CreateClusterTemplate will create a random cluster tempalte. An error will be returned if the
19// cluster-template could not be created.
20func CreateClusterTemplate(t *testing.T, client *gophercloud.ServiceClient) (*clustertemplates.ClusterTemplate, error) {
21	choices, err := clients.AcceptanceTestChoicesFromEnv()
22	if err != nil {
23		return nil, err
24	}
25
26	name := tools.RandomString("TESTACC-", 8)
27	t.Logf("Attempting to create cluster template: %s", name)
28
29	boolFalse := false
30	createOpts := clustertemplates.CreateOpts{
31		COE:                 "swarm",
32		DNSNameServer:       "8.8.8.8",
33		DockerStorageDriver: "devicemapper",
34		ExternalNetworkID:   choices.ExternalNetworkID,
35		FlavorID:            choices.FlavorID,
36		FloatingIPEnabled:   &boolFalse,
37		ImageID:             choices.MagnumImageID,
38		MasterFlavorID:      choices.FlavorID,
39		MasterLBEnabled:     &boolFalse,
40		Name:                name,
41		Public:              &boolFalse,
42		RegistryEnabled:     &boolFalse,
43		ServerType:          "vm",
44	}
45
46	res := clustertemplates.Create(client, createOpts)
47	if res.Err != nil {
48		return nil, res.Err
49	}
50
51	requestID := res.Header.Get("X-OpenStack-Request-Id")
52	th.AssertEquals(t, true, requestID != "")
53
54	t.Logf("Cluster Template %s request ID: %s", name, requestID)
55
56	clusterTemplate, err := res.Extract()
57	if err != nil {
58		return nil, err
59	}
60
61	t.Logf("Successfully created cluster template: %s", clusterTemplate.Name)
62
63	tools.PrintResource(t, clusterTemplate)
64	tools.PrintResource(t, clusterTemplate.CreatedAt)
65
66	th.AssertEquals(t, name, clusterTemplate.Name)
67	th.AssertEquals(t, choices.ExternalNetworkID, clusterTemplate.ExternalNetworkID)
68	th.AssertEquals(t, choices.MagnumImageID, clusterTemplate.ImageID)
69
70	return clusterTemplate, nil
71}
72
73// DeleteClusterTemplate will delete a given cluster-template. A fatal error will occur if the
74// cluster-template could not be deleted. This works best as a deferred function.
75func DeleteClusterTemplate(t *testing.T, client *gophercloud.ServiceClient, id string) {
76	t.Logf("Attempting to delete cluster-template: %s", id)
77
78	err := clustertemplates.Delete(client, id).ExtractErr()
79	if err != nil {
80		t.Fatalf("Error deleting cluster-template %s: %s:", id, err)
81	}
82
83	t.Logf("Successfully deleted cluster-template: %s", id)
84
85	return
86}
87
88// CreateCluster will create a random cluster. An error will be returned if the
89// cluster could not be created.
90func CreateCluster(t *testing.T, client *gophercloud.ServiceClient, clusterTemplateID string) (string, error) {
91	clusterName := tools.RandomString("TESTACC-", 8)
92	t.Logf("Attempting to create cluster: %s using template %s", clusterName, clusterTemplateID)
93
94	choices, err := clients.AcceptanceTestChoicesFromEnv()
95	if err != nil {
96		return "", err
97	}
98
99	masterCount := 1
100	nodeCount := 1
101	createTimeout := 100
102	createOpts := clusters.CreateOpts{
103		ClusterTemplateID: clusterTemplateID,
104		CreateTimeout:     &createTimeout,
105		FlavorID:          choices.FlavorID,
106		Keypair:           choices.MagnumKeypair,
107		Labels:            map[string]string{},
108		MasterCount:       &masterCount,
109		MasterFlavorID:    choices.FlavorID,
110		Name:              clusterName,
111		NodeCount:         &nodeCount,
112	}
113
114	createResult := clusters.Create(client, createOpts)
115	th.AssertNoErr(t, createResult.Err)
116	if len(createResult.Header["X-Openstack-Request-Id"]) > 0 {
117		t.Logf("Cluster Create Request ID: %s", createResult.Header["X-Openstack-Request-Id"][0])
118	}
119
120	clusterID, err := createResult.Extract()
121	if err != nil {
122		return "", err
123	}
124
125	t.Logf("Cluster created: %+v", clusterID)
126
127	err = WaitForCluster(client, clusterID, "CREATE_COMPLETE")
128	if err != nil {
129		return clusterID, err
130	}
131
132	t.Logf("Successfully created cluster: %s id: %s", clusterName, clusterID)
133	return clusterID, nil
134}
135
136func DeleteCluster(t *testing.T, client *gophercloud.ServiceClient, id string) {
137	t.Logf("Attempting to delete cluster: %s", id)
138
139	r := clusters.Delete(client, id)
140	err := clusters.Delete(client, id).ExtractErr()
141	deleteRequestID := ""
142	idKey := "X-Openstack-Request-Id"
143	if len(r.Header[idKey]) > 0 {
144		deleteRequestID = r.Header[idKey][0]
145	}
146	if err != nil {
147		t.Fatalf("Error deleting cluster. requestID=%s clusterID=%s: err%s:", deleteRequestID, id, err)
148	}
149
150	err = WaitForCluster(client, id, "DELETE_COMPLETE")
151	if err != nil {
152		t.Fatalf("Error deleting cluster %s: %s:", id, err)
153	}
154
155	t.Logf("Successfully deleted cluster: %s", id)
156
157	return
158}
159
160func WaitForCluster(client *gophercloud.ServiceClient, clusterID string, status string) error {
161	return tools.WaitFor(func() (bool, error) {
162		cluster, err := clusters.Get(client, clusterID).Extract()
163		if err != nil {
164			if _, ok := err.(gophercloud.ErrDefault404); ok && status == "DELETE_COMPLETE" {
165				return true, nil
166			}
167
168			return false, err
169		}
170
171		if cluster.Status == status {
172			return true, nil
173		}
174
175		if strings.Contains(cluster.Status, "FAILED") {
176			return false, fmt.Errorf("Cluster %s FAILED. Status=%s StatusReason=%s", clusterID, cluster.Status, cluster.StatusReason)
177		}
178
179		return false, nil
180	})
181}
182
183// CreateQuota will create a random quota. An error will be returned if the
184// quota could not be created.
185func CreateQuota(t *testing.T, client *gophercloud.ServiceClient) (*quotas.Quotas, error) {
186	name := tools.RandomString("TESTACC-", 8)
187	t.Logf("Attempting to create quota: %s", name)
188
189	idClient, err := clients.NewIdentityV3Client()
190	th.AssertNoErr(t, err)
191
192	project, err := idv3.CreateProject(t, idClient, nil)
193	th.AssertNoErr(t, err)
194	defer idv3.DeleteProject(t, idClient, project.ID)
195
196	createOpts := quotas.CreateOpts{
197		Resource:  "Cluster",
198		ProjectID: project.ID,
199		HardLimit: 10,
200	}
201
202	res := quotas.Create(client, createOpts)
203	if res.Err != nil {
204		return nil, res.Err
205	}
206
207	requestID := res.Header.Get("X-OpenStack-Request-Id")
208	th.AssertEquals(t, true, requestID != "")
209
210	t.Logf("Quota %s request ID: %s", name, requestID)
211
212	quota, err := res.Extract()
213	if err == nil {
214		t.Logf("Successfully created quota: %s", quota.ProjectID)
215
216		tools.PrintResource(t, quota)
217
218		th.AssertEquals(t, project.ID, quota.ProjectID)
219		th.AssertEquals(t, "Cluster", quota.Resource)
220		th.AssertEquals(t, 10, quota.HardLimit)
221	}
222
223	return quota, err
224}
225