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  }