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-----`