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