github.com/chenbh/concourse/v6@v6.4.2/fly/integration/suite_test.go (about)

     1  package integration_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"os"
    10  	"os/exec"
    11  	"path/filepath"
    12  	"runtime"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/chenbh/concourse/v6/atc"
    17  	"github.com/chenbh/concourse/v6/atc/db"
    18  	"github.com/chenbh/concourse/v6/fly/rc"
    19  	"github.com/chenbh/concourse/v6/skymarshal/token"
    20  	. "github.com/onsi/ginkgo"
    21  	. "github.com/onsi/gomega"
    22  	"github.com/onsi/gomega/gexec"
    23  	"github.com/onsi/gomega/ghttp"
    24  	"gopkg.in/square/go-jose.v2/jwt"
    25  )
    26  
    27  var flyPath string
    28  var homeDir string
    29  
    30  var atcServer *ghttp.Server
    31  
    32  const targetName = "testserver"
    33  const teamName = "main"
    34  const atcVersion = "4.0.0"
    35  const workerVersion = "4.5.6"
    36  
    37  var teams = []atc.Team{
    38  	atc.Team{
    39  		ID:   1,
    40  		Name: "main",
    41  	},
    42  	atc.Team{
    43  		ID:   2,
    44  		Name: "other-team",
    45  	},
    46  }
    47  
    48  var _ = SynchronizedBeforeSuite(func() []byte {
    49  	binPath, err := gexec.Build("github.com/chenbh/concourse/v6/fly")
    50  	Expect(err).NotTo(HaveOccurred())
    51  
    52  	return []byte(binPath)
    53  }, func(data []byte) {
    54  	flyPath = string(data)
    55  
    56  	SetDefaultEventuallyTimeout(10 * time.Second)
    57  })
    58  
    59  var _ = SynchronizedAfterSuite(func() {
    60  }, func() {
    61  	gexec.CleanupBuildArtifacts()
    62  })
    63  
    64  func infoHandler() http.HandlerFunc {
    65  	return ghttp.CombineHandlers(
    66  		ghttp.VerifyRequest("GET", "/api/v1/info"),
    67  		ghttp.RespondWithJSONEncoded(200, atc.Info{Version: atcVersion, WorkerVersion: workerVersion}),
    68  	)
    69  }
    70  
    71  func tokenHandler() http.HandlerFunc {
    72  	return ghttp.CombineHandlers(
    73  		ghttp.VerifyRequest("POST", "/sky/issuer/token"),
    74  		ghttp.RespondWithJSONEncoded(
    75  			200,
    76  			oauthToken(),
    77  		),
    78  	)
    79  }
    80  
    81  func userInfoHandler() http.HandlerFunc {
    82  	return ghttp.CombineHandlers(
    83  		ghttp.VerifyRequest("GET", "/api/v1/user"),
    84  		ghttp.RespondWithJSONEncoded(200, map[string]interface{}{
    85  			"user_name": "user",
    86  			"teams": map[string][]string{
    87  				teamName:          {"owner"},
    88  				"some-team":       {"owner"},
    89  				"some-other-team": {"owner"},
    90  			},
    91  		}),
    92  	)
    93  }
    94  
    95  func validAccessToken(expiry time.Time) string {
    96  	accessToken, err := token.Factory{}.GenerateAccessToken(db.Claims{
    97  		Claims: jwt.Claims{Expiry: jwt.NewNumericDate(expiry)}},
    98  	)
    99  	if err != nil {
   100  		panic(err)
   101  	}
   102  	return accessToken
   103  }
   104  
   105  func oauthToken() map[string]string {
   106  	return map[string]string{
   107  		"token_type":   "Bearer",
   108  		"access_token": validAccessToken(time.Now()),
   109  		"id_token":     "some-token",
   110  	}
   111  }
   112  
   113  func date(year int, month time.Month, day int) time.Time {
   114  	return time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
   115  }
   116  
   117  func createFlyRc(targets rc.Targets) {
   118  	flyrc := filepath.Join(homeDir, ".flyrc")
   119  
   120  	flyrcBytes, err := json.Marshal(rc.RC{Targets: targets})
   121  	if err != nil {
   122  		panic(err)
   123  	}
   124  
   125  	err = ioutil.WriteFile(flyrc, flyrcBytes, 0600)
   126  	if err != nil {
   127  		panic(err)
   128  	}
   129  }
   130  
   131  var _ = BeforeEach(func() {
   132  	atcServer = ghttp.NewServer()
   133  
   134  	atcServer.AppendHandlers(
   135  		infoHandler(),
   136  		tokenHandler(),
   137  		userInfoHandler(),
   138  		infoHandler(),
   139  	)
   140  
   141  	var err error
   142  
   143  	homeDir, err = ioutil.TempDir("", "fly-test")
   144  	Expect(err).NotTo(HaveOccurred())
   145  
   146  	os.Setenv("HOME", homeDir)
   147  	loginCmd := exec.Command(flyPath, "-t", targetName, "login", "-u", "user", "-p", "pass", "-c", atcServer.URL(), "-n", teamName)
   148  
   149  	session, err := gexec.Start(loginCmd, GinkgoWriter, GinkgoWriter)
   150  	Expect(err).NotTo(HaveOccurred())
   151  
   152  	<-session.Exited
   153  
   154  	Expect(session.ExitCode()).To(Equal(0))
   155  })
   156  
   157  var _ = AfterEach(func() {
   158  	atcServer.Close()
   159  	os.RemoveAll(homeDir)
   160  })
   161  
   162  func TestIntegration(t *testing.T) {
   163  	RegisterFailHandler(Fail)
   164  	RunSpecs(t, "Integration Suite")
   165  }
   166  
   167  func osFlag(short string, long string) string {
   168  	if runtime.GOOS == "windows" {
   169  		return fmt.Sprintf("/%s, /%s", short, long)
   170  	} else {
   171  		return fmt.Sprintf("-%s, --%s", short, long)
   172  	}
   173  }
   174  
   175  func userHomeDir() string {
   176  	return os.Getenv("HOME")
   177  }
   178  
   179  func Change(fn func() int) *changeMatcher {
   180  	return &changeMatcher{
   181  		fn: fn,
   182  	}
   183  }
   184  
   185  type changeMatcher struct {
   186  	fn     func() int
   187  	amount int
   188  
   189  	before int
   190  	after  int
   191  }
   192  
   193  func (cm *changeMatcher) By(amount int) *changeMatcher {
   194  	cm.amount = amount
   195  
   196  	return cm
   197  }
   198  
   199  func (cm *changeMatcher) Match(actual interface{}) (success bool, err error) {
   200  	cm.before = cm.fn()
   201  
   202  	ac, ok := actual.(func())
   203  	if !ok {
   204  		return false, errors.New("expected a function")
   205  	}
   206  
   207  	ac()
   208  
   209  	cm.after = cm.fn()
   210  
   211  	return (cm.after - cm.before) == cm.amount, nil
   212  }
   213  
   214  func (cm *changeMatcher) FailureMessage(actual interface{}) (message string) {
   215  	return fmt.Sprintf("Expected value to change by %d but it changed from %d to %d", cm.amount, cm.before, cm.after)
   216  }
   217  
   218  func (cm *changeMatcher) NegatedFailureMessage(actual interface{}) (message string) {
   219  	return fmt.Sprintf("Expected value not to change by %d but it changed from %d to %d", cm.amount, cm.before, cm.after)
   220  }
   221  
   222  const serverCert = `-----BEGIN CERTIFICATE-----
   223  MIIC+DCCAeCgAwIBAgIRAK3uVYcWQA/y8Q8wHWnm0YgwDQYJKoZIhvcNAQELBQAw
   224  EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MDgyMzExMTFaFw0yNjA4MDYyMzEx
   225  MTFaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
   226  ggEKAoIBAQC+qY2Pfr79ltRLudcX45AyUPmOm0DwF2gE8HUihljtQmeWno5Gc2Uc
   227  MqRrs7sfu90geL9ZBU7jYjhFxdlbsIO6710J0+uElLPKgSPI0sJDL3aoIi7jd+mi
   228  qTyQ/OErOxtTOe7V3xUjAS9HrIcqVxKQFGwIic5sIOWhdg5zbVqoCI8eX5QHdxST
   229  zNtoJYeCnCC5P7fdZySZ7lH5Y3HLgQWsVFyqoklKiYVmK1AyOQsZqrfOg1QjkXp9
   230  xKN/Z0EsRsBGItvEnzQdVlaFFdo9yKnuWDzNvdwWJUpH/pdv6SOzvunAhZrNHe8w
   231  DWUeLA6L5E8AvLR9KnT+BBCvygFu8njVAgMBAAGjSTBHMA4GA1UdDwEB/wQEAwIC
   232  pDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA8GA1UdEQQI
   233  MAaHBH8AAAEwDQYJKoZIhvcNAQELBQADggEBAHPBHI8Vx/lD8KIPRBSfY2+XSXKQ
   234  z4dHRFQxC4+hUm5X39Dg++ZgbHf5/Iv3T8466CW3DADCRamEpKmNK0/MAizDRmb2
   235  sQ6qCVO5CrljEPgECY9MIV2MknbRIK6J0WhUEkTNY/RkGyLOkgGFD5Fadorf/b9D
   236  0MKeDOl3xGIoDMz1qGS/ByiUXlu/5Dze3EKigtTI74z8GYIo/eAswfh3sIi0X7KR
   237  vgkHttWh9tkfjV9IxuG/yCAnPTlCN7UI8YTZIH+SPqFakS8cIBzmVlOnZBsH4u2/
   238  wtISX1uF4BH/i+knckhiG5mHNVSOVyUlZvC8lZR2hRMkeXVb/uns66Z/fSE=
   239  -----END CERTIFICATE-----
   240  `
   241  
   242  const serverKey = `-----BEGIN RSA PRIVATE KEY-----
   243  MIIEowIBAAKCAQEAvqmNj36+/ZbUS7nXF+OQMlD5jptA8BdoBPB1IoZY7UJnlp6O
   244  RnNlHDKka7O7H7vdIHi/WQVO42I4RcXZW7CDuu9dCdPrhJSzyoEjyNLCQy92qCIu
   245  43fpoqk8kPzhKzsbUznu1d8VIwEvR6yHKlcSkBRsCInObCDloXYOc21aqAiPHl+U
   246  B3cUk8zbaCWHgpwguT+33Wckme5R+WNxy4EFrFRcqqJJSomFZitQMjkLGaq3zoNU
   247  I5F6fcSjf2dBLEbARiLbxJ80HVZWhRXaPcip7lg8zb3cFiVKR/6Xb+kjs77pwIWa
   248  zR3vMA1lHiwOi+RPALy0fSp0/gQQr8oBbvJ41QIDAQABAoIBAAzM9WQc7lW4Oqia
   249  4YYJETVPmnGomsODzsgGHNckjfPf8XR7ULIKLU+nVsKkXnvS8RWtBavEX3eEsKJ+
   250  lglB4JY8W9K9F6LfGPMPmIdzHvfDyAOhx+QduOHi2t4hHDz6yurbiN1zDMg83B/D
   251  xY9iKSzjMh2gous/iis88dtuDBgb3RV903oiNJmTmHbZiClSEe9r3TWfOlxVMH0B
   252  kFMvsnvRDomDzyfnjDTK+C8fPp07O3/uIM8rbOJaVEBYOVKj/pFlYA0HHY4g+sq5
   253  zYSGzOLJLCVooU8hOYq3DuhYuFliziGDJZx3vg08GKVYwmcBaIlmYxPtFScyliKx
   254  vRTFEgECgYEAwgj0ZUPA/DHyCtydwKUXjCV+j5uQJwDfes2qFDGbhcT6xkoGIM3S
   255  EQl+Lu3NlRXJqZZfyZjurCuK9hOMIWK7Brlm/TyDV5CnOSK86/ez4mOL7mf802zZ
   256  +aMqITebdj1BMLa3IGZhsw4hguLHQ7qelvJpyE/7531OEcyH6AB29MkCgYEA+4zf
   257  BkW1PO7gSAZLU0RA5mkPjLV61OVrL3q7Yfq1sYC+dD/kQ7ug36ElZKLwtnPyPB2D
   258  Yb0fxwDRCAeF2VZE58gVJwC1xtVhVI7DgXRgGdXZZq8EmW5/308mwLov2RfR/4lE
   259  SgQ2gLruVZSt4hqXqmT2CV2UbKwDapDhTEC+Ja0CgYB8s5KWLjguHM9Iycac071R
   260  dZtkIf9AAeCepOTEu6kPDKx6mYJcvMpf5rDw6iYwxWLomdsPzji97/IL+j4aCsDW
   261  LnuRDr3+ndnK75dpM7WpLn71BmHHY3KnbISb+ofwMqfd7d+9c+8gS1mgK60SyzI3
   262  Iq53bWgguzhcWg2SPhI1eQKBgQDJwJODwVb6NxDVU48Iip6O7kaVcVzB8ftEymgN
   263  znn5kquuKyxWEt+VXPbTv0fW3imzg2xDcN9SydndWcNFrEZ5q+UjMhOZFL0Kh7JQ
   264  WtlU/0ptbAQBVzniDeaj/vCvasZ38E1AHB7moobTRvsrdG6eMHmQy2hmvJPE3cyF
   265  TwvyxQKBgEBP37kUkMg2D3JtnKJZX3r0DKf/3fvDXU+nsOipxF+QVi7SMt/30j2d
   266  cGvJLpKX8qu9LOLGoVaB1yxEO8DO5B2YxdG/sjMBLlN+JSMFQ734VEIWD+1LiBvQ
   267  JBf0Z15NGOY3w9KSxeiTPFyXU4/RmymDzyd/VKcnPBMKqTvbqT2G
   268  -----END RSA PRIVATE KEY-----`