1//
2// Copyright (c) 2018, Joyent, Inc. All rights reserved.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7//
8
9package testutils
10
11import (
12	"errors"
13	"fmt"
14	"log"
15	"os"
16	"testing"
17
18	triton "github.com/joyent/triton-go"
19	"github.com/joyent/triton-go/authentication"
20)
21
22const TestEnvVar = "TRITON_TEST"
23
24type TestCase struct {
25	Steps []Step
26	State TritonStateBag
27}
28
29func AccTest(t *testing.T, c TestCase) {
30	// We only run acceptance tests if an env var is set because they're
31	// slow and generally require some outside configuration.
32	if os.Getenv(TestEnvVar) == "" {
33		t.Skip(fmt.Sprintf(
34			"Acceptance tests skipped unless env '%s' set",
35			TestEnvVar))
36		return
37	}
38
39	// We require verbose mode so that the user knows what is going on.
40	if !testing.Verbose() {
41		t.Fatal("Acceptance tests must be run with the -v flag on tests")
42		return
43	}
44
45	tritonURL := triton.GetEnv("URL")
46	tritonAccount := triton.GetEnv("ACCOUNT")
47	tritonKeyID := triton.GetEnv("KEY_ID")
48	tritonKeyMaterial := triton.GetEnv("KEY_MATERIAL")
49	userName := triton.GetEnv("USER")
50	mantaURL := triton.GetEnv("MANTA_URL")
51
52	var prerollErrors []error
53	if tritonURL == "" {
54		prerollErrors = append(prerollErrors,
55			errors.New("The TRITON_URL environment variable must be set to run acceptance tests"))
56	}
57	if tritonAccount == "" {
58		prerollErrors = append(prerollErrors,
59			errors.New("The TRITON_ACCOUNT environment variable must be set to run acceptance tests"))
60	}
61	if tritonKeyID == "" {
62		prerollErrors = append(prerollErrors,
63			errors.New("The TRITON_KEY_ID environment variable must be set to run acceptance tests"))
64	}
65	if len(prerollErrors) > 0 {
66		for _, err := range prerollErrors {
67			t.Error(err)
68		}
69		t.FailNow()
70	}
71
72	var signer authentication.Signer
73	var err error
74	if tritonKeyMaterial != "" {
75		log.Println("[INFO] Creating Triton Client with Private Key Signer...")
76		input := authentication.PrivateKeySignerInput{
77			KeyID:              tritonKeyID,
78			PrivateKeyMaterial: []byte(tritonKeyMaterial),
79			AccountName:        tritonAccount,
80			Username:           userName,
81		}
82		signer, err = authentication.NewPrivateKeySigner(input)
83		if err != nil {
84			t.Fatalf("Error creating private key signer: %s", err)
85		}
86	} else {
87		log.Println("[INFO] Creating Triton Client with SSH Key Signer...")
88		input := authentication.SSHAgentSignerInput{
89			KeyID:       tritonKeyID,
90			AccountName: tritonAccount,
91			Username:    userName,
92		}
93		signer, err = authentication.NewSSHAgentSigner(input)
94		if err != nil {
95			t.Fatalf("Error creating SSH Agent signer: %s", err)
96		}
97	}
98
99	// Old world... we spun up a universal client. This is pushed deeper into
100	// the process within `testutils.StepClient`.
101	//
102	// client, err := NewClient(tritonURL, tritonAccount, signer)
103	// if err != nil {
104	//         t.Fatalf("Error creating Triton Client: %s", err)
105	// }
106
107	config := &triton.ClientConfig{
108		TritonURL:   tritonURL,
109		MantaURL:    mantaURL,
110		AccountName: tritonAccount,
111		Username:    userName,
112		Signers:     []authentication.Signer{signer},
113	}
114
115	state := &basicTritonStateBag{
116		TritonConfig: config,
117	}
118
119	runner := &basicRunner{
120		Steps: c.Steps,
121	}
122
123	runner.Run(state)
124
125	if errs := state.ErrorsOrNil(); errs != nil {
126		for _, err := range errs {
127			t.Error(err)
128		}
129		t.Fatal("\n\nThere may be dangling resources in your Triton account!")
130	}
131}
132