github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/e2e/framework/provisioner.go (about)

     1  package framework
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  
     8  	capi "github.com/hashicorp/consul/api"
     9  	napi "github.com/hashicorp/nomad/api"
    10  	"github.com/hashicorp/nomad/helper/uuid"
    11  	vapi "github.com/hashicorp/vault/api"
    12  )
    13  
    14  // ClusterInfo is a handle to a provisioned cluster, along with clients
    15  // a test run can use to connect to the cluster.
    16  type ClusterInfo struct {
    17  	ID           string
    18  	Name         string
    19  	NomadClient  *napi.Client
    20  	ConsulClient *capi.Client
    21  	VaultClient  *vapi.Client
    22  }
    23  
    24  // SetupOptions defines options to be given to the Provisioner when
    25  // calling Setup* methods.
    26  type SetupOptions struct {
    27  	Name         string
    28  	ExpectConsul bool // If true, fails if a Consul client can't be configured
    29  	ExpectVault  bool // If true, fails if a Vault client can't be configured
    30  }
    31  
    32  // Provisioner interface is used by the test framework to provision API
    33  // clients for a Nomad cluster, with the possibility of extending to provision
    34  // standalone clusters for each test case in the future.
    35  //
    36  // The Setup* methods are hooks that get run at the appropriate stage. They
    37  // return a ClusterInfo handle that helps TestCases isolate test state if
    38  // they use the ClusterInfo.ID as part of job IDs.
    39  //
    40  // The TearDown* methods are hooks to clean up provisioned cluster state
    41  // that isn't covered by the test case's implementation of AfterEachTest.
    42  type Provisioner interface {
    43  	// SetupTestRun is called at the start of the entire test run.
    44  	SetupTestRun(t *testing.T, opts SetupOptions) (*ClusterInfo, error)
    45  
    46  	// SetupTestSuite is called at the start of each TestSuite.
    47  	// TODO: no current provisioner implementation uses this, but we
    48  	// could use it to provide each TestSuite with an entirely separate
    49  	// Nomad cluster.
    50  	SetupTestSuite(t *testing.T, opts SetupOptions) (*ClusterInfo, error)
    51  
    52  	// SetupTestCase is called at the start of each TestCase in every TestSuite.
    53  	SetupTestCase(t *testing.T, opts SetupOptions) (*ClusterInfo, error)
    54  
    55  	// TODO: no current provisioner implementation uses any of these,
    56  	// but it's the obvious need if we setup/teardown after each TestSuite
    57  	// or TestCase.
    58  
    59  	// TearDownTestCase is called after each TestCase in every TestSuite.
    60  	TearDownTestCase(t *testing.T, clusterID string) error
    61  
    62  	// TearDownTestSuite is called after every TestSuite.
    63  	TearDownTestSuite(t *testing.T, clusterID string) error
    64  
    65  	// TearDownTestRun is called at the end of the entire test run.
    66  	TearDownTestRun(t *testing.T, clusterID string) error
    67  }
    68  
    69  // DefaultProvisioner is a Provisioner that doesn't deploy a Nomad cluster
    70  // (because that's handled by Terraform elsewhere), but build clients from
    71  // environment variables.
    72  var DefaultProvisioner Provisioner = new(singleClusterProvisioner)
    73  
    74  type singleClusterProvisioner struct{}
    75  
    76  // SetupTestRun in the default case is a no-op.
    77  func (p *singleClusterProvisioner) SetupTestRun(t *testing.T, opts SetupOptions) (*ClusterInfo, error) {
    78  	return &ClusterInfo{ID: "framework", Name: "framework"}, nil
    79  }
    80  
    81  // SetupTestSuite in the default case is a no-op.
    82  func (p *singleClusterProvisioner) SetupTestSuite(t *testing.T, opts SetupOptions) (*ClusterInfo, error) {
    83  	return &ClusterInfo{
    84  		ID:   uuid.Generate()[:8],
    85  		Name: opts.Name,
    86  	}, nil
    87  }
    88  
    89  // SetupTestCase in the default case only creates new clients and embeds the
    90  // TestCase name into the ClusterInfo handle.
    91  func (p *singleClusterProvisioner) SetupTestCase(t *testing.T, opts SetupOptions) (*ClusterInfo, error) {
    92  	// Build ID based off given name
    93  	info := &ClusterInfo{
    94  		ID:   uuid.Generate()[:8],
    95  		Name: opts.Name,
    96  	}
    97  
    98  	// Build Nomad api client
    99  	nomadClient, err := napi.NewClient(napi.DefaultConfig())
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	info.NomadClient = nomadClient
   104  
   105  	if opts.ExpectConsul {
   106  		consulClient, err := capi.NewClient(capi.DefaultConfig())
   107  		if err != nil {
   108  			return nil, fmt.Errorf("expected Consul: %v", err)
   109  		}
   110  		info.ConsulClient = consulClient
   111  	}
   112  
   113  	if len(os.Getenv(vapi.EnvVaultAddress)) != 0 {
   114  		vaultClient, err := vapi.NewClient(vapi.DefaultConfig())
   115  		if err != nil && opts.ExpectVault {
   116  			return nil, err
   117  		}
   118  		info.VaultClient = vaultClient
   119  	} else if opts.ExpectVault {
   120  		return nil, fmt.Errorf("vault client expected but environment variable %s not set",
   121  			vapi.EnvVaultAddress)
   122  	}
   123  
   124  	return info, err
   125  }
   126  
   127  // all TearDown* methods of the default provisioner leave the test environment in place
   128  
   129  func (p *singleClusterProvisioner) TearDownTestCase(_ *testing.T, _ string) error  { return nil }
   130  func (p *singleClusterProvisioner) TearDownTestSuite(_ *testing.T, _ string) error { return nil }
   131  func (p *singleClusterProvisioner) TearDownTestRun(_ *testing.T, _ string) error   { return nil }