github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/internal/acceptance/openstack/containerinfra/v1/containerinfra.go (about) 1 package v1 2 3 import ( 4 "context" 5 "fmt" 6 "math" 7 "net/http" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/vnpaycloud-console/gophercloud/v2" 13 "github.com/vnpaycloud-console/gophercloud/v2/internal/acceptance/clients" 14 idv3 "github.com/vnpaycloud-console/gophercloud/v2/internal/acceptance/openstack/identity/v3" 15 "github.com/vnpaycloud-console/gophercloud/v2/internal/acceptance/tools" 16 "github.com/vnpaycloud-console/gophercloud/v2/openstack/containerinfra/v1/clusters" 17 "github.com/vnpaycloud-console/gophercloud/v2/openstack/containerinfra/v1/clustertemplates" 18 "github.com/vnpaycloud-console/gophercloud/v2/openstack/containerinfra/v1/quotas" 19 th "github.com/vnpaycloud-console/gophercloud/v2/testhelper" 20 ) 21 22 // CreateClusterTemplateCOE will create a random cluster template for the specified orchestration engine. 23 // An error will be returned if the cluster template could not be created. 24 func CreateClusterTemplateCOE(t *testing.T, client *gophercloud.ServiceClient, coe string) (*clustertemplates.ClusterTemplate, error) { 25 choices, err := clients.AcceptanceTestChoicesFromEnv() 26 if err != nil { 27 return nil, err 28 } 29 30 name := tools.RandomString("TESTACC-", 8) 31 t.Logf("Attempting to create %s cluster template: %s", coe, name) 32 33 boolFalse := false 34 createOpts := clustertemplates.CreateOpts{ 35 COE: coe, 36 DNSNameServer: "8.8.8.8", 37 DockerStorageDriver: "overlay2", 38 ExternalNetworkID: choices.ExternalNetworkID, 39 FlavorID: choices.FlavorID, 40 FloatingIPEnabled: &boolFalse, 41 ImageID: choices.MagnumImageID, 42 MasterFlavorID: choices.FlavorID, 43 MasterLBEnabled: &boolFalse, 44 Name: name, 45 Public: &boolFalse, 46 RegistryEnabled: &boolFalse, 47 ServerType: "vm", 48 } 49 50 res := clustertemplates.Create(context.TODO(), client, createOpts) 51 if res.Err != nil { 52 return nil, res.Err 53 } 54 55 requestID := res.Header.Get("X-OpenStack-Request-Id") 56 th.AssertEquals(t, true, requestID != "") 57 58 t.Logf("Cluster Template %s request ID: %s", name, requestID) 59 60 clusterTemplate, err := res.Extract() 61 if err != nil { 62 return nil, err 63 } 64 65 t.Logf("Successfully created cluster template: %s", clusterTemplate.Name) 66 67 tools.PrintResource(t, clusterTemplate) 68 tools.PrintResource(t, clusterTemplate.CreatedAt) 69 70 th.AssertEquals(t, name, clusterTemplate.Name) 71 th.AssertEquals(t, choices.ExternalNetworkID, clusterTemplate.ExternalNetworkID) 72 th.AssertEquals(t, choices.MagnumImageID, clusterTemplate.ImageID) 73 74 return clusterTemplate, nil 75 } 76 77 // CreateClusterTemplate will create a random swarm cluster template. 78 // An error will be returned if the cluster template could not be created. 79 func CreateClusterTemplate(t *testing.T, client *gophercloud.ServiceClient) (*clustertemplates.ClusterTemplate, error) { 80 return CreateClusterTemplateCOE(t, client, "swarm") 81 } 82 83 // CreateKubernetesClusterTemplate will create a random kubernetes cluster template. 84 // An error will be returned if the cluster template could not be created. 85 func CreateKubernetesClusterTemplate(t *testing.T, client *gophercloud.ServiceClient) (*clustertemplates.ClusterTemplate, error) { 86 return CreateClusterTemplateCOE(t, client, "kubernetes") 87 } 88 89 // DeleteClusterTemplate will delete a given cluster-template. A fatal error will occur if the 90 // cluster-template could not be deleted. This works best as a deferred function. 91 func DeleteClusterTemplate(t *testing.T, client *gophercloud.ServiceClient, id string) { 92 t.Logf("Attempting to delete cluster-template: %s", id) 93 94 err := clustertemplates.Delete(context.TODO(), client, id).ExtractErr() 95 if err != nil { 96 t.Fatalf("Error deleting cluster-template %s: %s:", id, err) 97 } 98 99 t.Logf("Successfully deleted cluster-template: %s", id) 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(context.TODO(), 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(context.TODO(), client, id) 166 err := clusters.Delete(context.TODO(), 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 184 func WaitForCluster(client *gophercloud.ServiceClient, clusterID string, status string, timeout time.Duration) error { 185 return tools.WaitForTimeout(func(ctx context.Context) (bool, error) { 186 cluster, err := clusters.Get(ctx, client, clusterID).Extract() 187 if err != nil { 188 if gophercloud.ResponseCodeIs(err, http.StatusNotFound) && status == "DELETE_COMPLETE" { 189 return true, nil 190 } 191 192 return false, err 193 } 194 195 if cluster.Status == status { 196 return true, nil 197 } 198 199 if strings.Contains(cluster.Status, "FAILED") { 200 return false, fmt.Errorf("Cluster %s FAILED. Status=%s StatusReason=%s", clusterID, cluster.Status, cluster.StatusReason) 201 } 202 203 return false, nil 204 }, timeout) 205 } 206 207 // CreateQuota will create a random quota. An error will be returned if the 208 // quota could not be created. 209 func CreateQuota(t *testing.T, client *gophercloud.ServiceClient) (*quotas.Quotas, error) { 210 name := tools.RandomString("TESTACC-", 8) 211 t.Logf("Attempting to create quota: %s", name) 212 213 idClient, err := clients.NewIdentityV3Client() 214 th.AssertNoErr(t, err) 215 216 project, err := idv3.CreateProject(t, idClient, nil) 217 th.AssertNoErr(t, err) 218 defer idv3.DeleteProject(t, idClient, project.ID) 219 220 createOpts := quotas.CreateOpts{ 221 Resource: "Cluster", 222 ProjectID: project.ID, 223 HardLimit: 10, 224 } 225 226 res := quotas.Create(context.TODO(), client, createOpts) 227 if res.Err != nil { 228 return nil, res.Err 229 } 230 231 requestID := res.Header.Get("X-OpenStack-Request-Id") 232 th.AssertEquals(t, true, requestID != "") 233 234 t.Logf("Quota %s request ID: %s", name, requestID) 235 236 quota, err := res.Extract() 237 if err == nil { 238 t.Logf("Successfully created quota: %s", quota.ProjectID) 239 240 tools.PrintResource(t, quota) 241 242 th.AssertEquals(t, project.ID, quota.ProjectID) 243 th.AssertEquals(t, "Cluster", quota.Resource) 244 th.AssertEquals(t, 10, quota.HardLimit) 245 } 246 247 return quota, err 248 }