github.com/apprenda/kismatic@v1.12.0/integration-tests/framework.go (about)

     1  package integration_tests
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	. "github.com/onsi/ginkgo"
     8  	. "github.com/onsi/gomega"
     9  )
    10  
    11  // ItOnAWS runs a spec if the AWS details have been provided
    12  func ItOnAWS(description string, f func(infrastructureProvisioner)) {
    13  	Context("when using AWS infrastructure [aws]", func() {
    14  		It(description, func() {
    15  			awsClient, ok := AWSClientFromEnvironment()
    16  			if !ok {
    17  				Skip("AWS environment variables were not defined")
    18  			}
    19  			f(awsClient)
    20  		})
    21  	})
    22  }
    23  
    24  // ItOnPacket runs a spec if the Packet.Net details have been provided
    25  func ItOnPacket(description string, f func(infrastructureProvisioner)) {
    26  	Context("when using Packet.net infrastructure [packet]", func() {
    27  		It(description, func() {
    28  			packetClient, ok := packetClientFromEnv()
    29  			if !ok {
    30  				Skip("Packet environment variables were not defined")
    31  			}
    32  			f(packetClient)
    33  		})
    34  	})
    35  }
    36  
    37  type infraDependentTest func(nodes provisionedNodes, sshKey string)
    38  
    39  // WithInfrastructure runs the spec with the requested infrastructure
    40  func WithInfrastructure(nodeCount NodeCount, distro linuxDistro, provisioner infrastructureProvisioner, f infraDependentTest) {
    41  	By(fmt.Sprintf("Provisioning nodes: %+v", nodeCount))
    42  	start := time.Now()
    43  	nodes, err := provisioner.ProvisionNodes(nodeCount, distro)
    44  	if !leaveIt() {
    45  		defer provisioner.TerminateNodes(nodes)
    46  	}
    47  	Expect(err).ToNot(HaveOccurred())
    48  	fmt.Println("Provisioning infrastructure took", time.Since(start))
    49  
    50  	By("Waiting until nodes are SSH-accessible")
    51  	start = time.Now()
    52  	sshKey := provisioner.SSHKey()
    53  	err = waitForSSH(nodes, sshKey)
    54  	Expect(err).ToNot(HaveOccurred())
    55  	fmt.Println("Waiting for SSH took", time.Since(start))
    56  
    57  	f(nodes, sshKey)
    58  }
    59  
    60  // WithInfrastructureAndDNS runs the spec with the requested infrastructure and DNS
    61  func WithInfrastructureAndDNS(nodeCount NodeCount, distro linuxDistro, provisioner infrastructureProvisioner, f infraDependentTest) {
    62  	By(fmt.Sprintf("Provisioning nodes and DNS: %+v", nodeCount))
    63  	start := time.Now()
    64  	nodes, err := provisioner.ProvisionNodes(nodeCount, distro)
    65  	if !leaveIt() {
    66  		defer provisioner.TerminateNodes(nodes)
    67  	}
    68  	Expect(err).ToNot(HaveOccurred())
    69  	fmt.Println("Provisioning infrastructure took", time.Since(start))
    70  
    71  	By("Waiting until nodes are SSH-accessible")
    72  	start = time.Now()
    73  	sshKey := provisioner.SSHKey()
    74  	err = waitForSSH(nodes, sshKey)
    75  	Expect(err).ToNot(HaveOccurred())
    76  	fmt.Println("Waiting for SSH took", time.Since(start))
    77  
    78  	By("Configuring DNS entries")
    79  	start = time.Now()
    80  	var masterIPs []string
    81  	for _, node := range nodes.master {
    82  		masterIPs = append(masterIPs, node.PrivateIP)
    83  	}
    84  	dnsRecord, err := provisioner.ConfigureDNS(masterIPs)
    85  	nodes.dnsRecord = dnsRecord
    86  	Expect(err).ToNot(HaveOccurred())
    87  	if !leaveIt() {
    88  		By("Removing DNS entries")
    89  		defer provisioner.RemoveDNS(dnsRecord)
    90  	}
    91  	fmt.Println("Configuring DNS entries took", time.Since(start))
    92  
    93  	f(nodes, sshKey)
    94  }
    95  
    96  type miniInfraDependentTest func(node NodeDeets, sshKey string)
    97  
    98  // WithMiniInfrastructure runs the spec with a Minikube-like infrastructure setup.
    99  func WithMiniInfrastructure(distro linuxDistro, provisioner infrastructureProvisioner, f miniInfraDependentTest) {
   100  	By("Provisioning minikube node")
   101  	start := time.Now()
   102  	nodes, err := provisioner.ProvisionNodes(NodeCount{Worker: 1}, distro)
   103  	if !leaveIt() {
   104  		defer provisioner.TerminateNodes(nodes)
   105  	}
   106  	Expect(err).ToNot(HaveOccurred())
   107  	fmt.Println("Provisioning node took", time.Since(start))
   108  
   109  	By("Waiting until nodes are SSH-accessible")
   110  	start = time.Now()
   111  	sshKey := provisioner.SSHKey()
   112  	err = waitForSSH(nodes, sshKey)
   113  	Expect(err).ToNot(HaveOccurred())
   114  	fmt.Println("Waiting for SSH took", time.Since(start))
   115  
   116  	f(nodes.worker[0], sshKey)
   117  }
   118  
   119  // WithMiniInfrastructureAndBlockDevice  runs the spec with the requested infrastructure and an additiona block device
   120  // The block will be under /dev/xvdb on AWS
   121  func WithMiniInfrastructureAndBlockDevice(distro linuxDistro, provisioner infrastructureProvisioner, f miniInfraDependentTest) {
   122  	By("Provisioning minikube node")
   123  	start := time.Now()
   124  	nodes, err := provisioner.ProvisionNodes(NodeCount{Worker: 1}, distro, []string{"block_device"}...)
   125  	if !leaveIt() {
   126  		defer provisioner.TerminateNodes(nodes)
   127  	}
   128  	Expect(err).ToNot(HaveOccurred())
   129  	fmt.Println("Provisioning node took", time.Since(start))
   130  
   131  	By("Waiting until nodes are SSH-accessible")
   132  	start = time.Now()
   133  	sshKey := provisioner.SSHKey()
   134  	err = waitForSSH(nodes, sshKey)
   135  	Expect(err).ToNot(HaveOccurred())
   136  	fmt.Println("Waiting for SSH took", time.Since(start))
   137  
   138  	f(nodes.worker[0], sshKey)
   139  }
   140  
   141  // SubDescribe allows you to define specifications inside another spec.
   142  // We have found the need for this because Gingko does not support
   143  // serializing a subset of tests when running in parallel. This means
   144  // that we must define multiple specs inside a parent It() block.
   145  // Use this when it is truly needed.
   146  //
   147  // Example:
   148  // Describe("the foo service", func() {
   149  //	It("should be deployed successfully", func() {
   150  //		// some assertions here...
   151  //		sub := SubDescribe("should return 200", func() error {
   152  //			// call service and return error if not 200
   153  //		})
   154  //	})
   155  // })
   156  func SubDescribe(name string) *subTest {
   157  	return &subTest{name: name}
   158  }
   159  
   160  type subTest struct {
   161  	name   string
   162  	specs  []string
   163  	errors []error
   164  }
   165  
   166  func (sub *subTest) It(name string, f func() error) {
   167  	By(fmt.Sprintf("Running spec: %s - %s", sub.name, name))
   168  	sub.specs = append(sub.specs, name)
   169  	sub.errors = append(sub.errors, f())
   170  }
   171  
   172  func (sub *subTest) Check() {
   173  	var failed bool
   174  	for _, e := range sub.errors {
   175  		if e != nil {
   176  			failed = true
   177  			break
   178  		}
   179  	}
   180  	if failed {
   181  		// Print report and fail test
   182  		sub.printReport()
   183  		Fail("Failed: " + sub.name)
   184  	}
   185  }
   186  
   187  func (sub *subTest) printReport() {
   188  	fmt.Println(sub.name)
   189  	for i, spec := range sub.specs {
   190  		if sub.errors[i] != nil {
   191  			fmt.Printf("%s: FAILED: %v\n", spec, sub.errors[i])
   192  		} else {
   193  			fmt.Printf("%s: PASSED\n", spec)
   194  		}
   195  	}
   196  }