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  }