Merge pull request #5955 from concourse/fix-fly-tokens

Fly commands don't assume tokens are JWTs
This commit is contained in:
Aidan Oldershaw 2020-08-10 10:38:19 -04:00 committed by GitHub
commit 203e2b3f9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 284 additions and 545 deletions

View File

@ -21,12 +21,12 @@ func (command *LogoutCommand) Execute(args []string) error {
fmt.Println("logged out of target: " + Fly.Target)
} else if Fly.Target == "" && command.All {
flyYAML, err := rc.LoadTargets()
targets, err := rc.LoadTargets()
if err != nil {
return err
}
for targetName := range flyYAML.Targets {
for targetName := range targets {
if err := rc.LogoutTarget(targetName); err != nil {
return err
}

View File

@ -5,7 +5,6 @@ import (
"github.com/concourse/concourse/fly/commands/internal/displayhelpers"
"github.com/concourse/concourse/fly/rc"
jwt "github.com/dgrijalva/jwt-go"
)
type StatusCommand struct{}
@ -23,21 +22,10 @@ func (c *StatusCommand) Execute([]string) error {
return nil
}
if tToken != nil {
_, err := jwt.Parse(tToken.Value, func(token *jwt.Token) (interface{}, error) {
return nil, token.Claims.Valid()
})
if err != nil && err.Error() != jwt.ErrInvalidKeyType.Error() {
displayhelpers.FailWithErrorf("please login again.\n\ntoken validation failed with error ", err)
return nil
}
_, err = target.Client().UserInfo()
if err != nil {
displayhelpers.FailWithErrorf("please login again.\n\ntoken validation failed with error ", err)
return nil
}
_, err = target.Client().UserInfo()
if err != nil {
displayhelpers.FailWithErrorf("please login again.\n\ntoken validation failed with error", err)
return nil
}
fmt.Println("logged in successfully")

View File

@ -1,22 +1,20 @@
package commands
import (
"fmt"
"os"
"sort"
"strconv"
"time"
"github.com/concourse/concourse/fly/rc"
"github.com/concourse/concourse/fly/ui"
"github.com/dgrijalva/jwt-go"
"github.com/concourse/concourse/skymarshal/token"
"github.com/fatih/color"
)
type TargetsCommand struct{}
func (command *TargetsCommand) Execute([]string) error {
flyYAML, err := rc.LoadTargets()
targets, err := rc.LoadTargets()
if err != nil {
return err
}
@ -30,7 +28,7 @@ func (command *TargetsCommand) Execute([]string) error {
},
}
for targetName, targetValues := range flyYAML.Targets {
for targetName, targetValues := range targets {
expirationTime := getExpirationFromString(targetValues.Token)
row := ui.TableRow{
@ -48,43 +46,15 @@ func (command *TargetsCommand) Execute([]string) error {
return table.Render(os.Stdout, Fly.PrintTableHeaders)
}
func getExpirationFromString(token *rc.TargetToken) string {
if token == nil || token.Type == "" || token.Value == "" {
func getExpirationFromString(ttoken *rc.TargetToken) string {
if ttoken == nil || ttoken.Type == "" || ttoken.Value == "" {
return "n/a"
}
parsedToken, err := jwt.Parse(token.Value, func(token *jwt.Token) (interface{}, error) {
return "", token.Claims.Valid()
})
if err != nil && err.Error() != jwt.ErrInvalidKeyType.Error() {
return fmt.Sprintf("n/a: %s", err)
expiry, err := token.Factory{}.ParseExpiry(ttoken.Value)
if err != nil {
return "n/a: invalid token"
}
claims := parsedToken.Claims.(jwt.MapClaims)
expClaim, ok := claims["exp"]
if !ok {
return "n/a"
}
var intSeconds int64
floatSeconds, ok := expClaim.(float64)
if ok {
intSeconds = int64(floatSeconds)
} else {
stringSeconds, ok := expClaim.(string)
if !ok {
return "n/a"
}
var err error
intSeconds, err = strconv.ParseInt(stringSeconds, 10, 64)
if err != nil {
return "n/a"
}
}
unixSeconds := time.Unix(intSeconds, 0).UTC()
return unixSeconds.Format(time.RFC1123)
return expiry.UTC().Format(time.RFC1123)
}

View File

@ -1,13 +1,9 @@
package integration_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/concourse/concourse/fly/rc"
"github.com/concourse/concourse/fly/ui"
"github.com/fatih/color"
@ -21,32 +17,19 @@ import (
var _ = Describe("Fly CLI", func() {
Describe("delete target", func() {
Describe("valid configuration", func() {
var (
flyrc string
tmpDir string
)
BeforeEach(func() {
var err error
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).NotTo(HaveOccurred())
if runtime.GOOS == "windows" {
os.Setenv("USERPROFILE", tmpDir)
os.Setenv("HOMEPATH", strings.TrimPrefix(tmpDir, os.Getenv("HOMEDRIVE")))
} else {
os.Setenv("HOME", tmpDir)
}
flyrc = filepath.Join(userHomeDir(), ".flyrc")
flyFixtureFile, err := os.OpenFile("./fixtures/flyrc.yml", os.O_RDONLY, 0600)
Expect(err).NotTo(HaveOccurred())
flyFixtureData, err := ioutil.ReadAll(flyFixtureFile)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
Expect(err).NotTo(HaveOccurred())
createFlyRc(rc.Targets{
"test1": {
API: "https://example.com/test1",
TeamName: "main",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 1))},
},
"test2": {
API: "https://example.com/test2",
TeamName: "main",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 2))},
},
})
flyCmd := exec.Command(flyPath, "targets")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
@ -62,21 +45,15 @@ var _ = Describe("Fly CLI", func() {
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "test1"}, {Contents: "https://example.com/test1"}, {Contents: "main"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
},
}))
})
AfterEach(func() {
os.RemoveAll(tmpDir)
})
Context("when fly target is specified", func() {
It("should delete target", func() {
flyCmd := exec.Command(flyPath, "-t", "test", "delete-target")
flyCmd := exec.Command(flyPath, "-t", "test1", "delete-target")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
@ -84,7 +61,7 @@ var _ = Describe("Fly CLI", func() {
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(gbytes.Say(`deleted target: test`))
Expect(sess.Out).To(gbytes.Say(`deleted target: test1`))
flyCmd = exec.Command(flyPath, "targets")
sess, err = gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
@ -99,9 +76,7 @@ var _ = Describe("Fly CLI", func() {
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
},
}))
})
@ -109,7 +84,7 @@ var _ = Describe("Fly CLI", func() {
Context("when configuration all", func() {
It("should delete all targets", func() {
flyCmd := exec.Command(flyPath, "-t", "test", "delete-target", "--all")
flyCmd := exec.Command(flyPath, "-t", "test1", "delete-target", "--all")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())

View File

@ -1,13 +1,9 @@
package integration_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/concourse/concourse/fly/rc"
"github.com/concourse/concourse/fly/ui"
"github.com/fatih/color"
@ -39,33 +35,19 @@ var _ = Describe("Fly CLI", func() {
})
Describe("valid configuration", func() {
var (
flyrc string
tmpDir string
)
BeforeEach(func() {
var err error
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).NotTo(HaveOccurred())
if runtime.GOOS == "windows" {
os.Setenv("USERPROFILE", tmpDir)
os.Setenv("HOMEPATH", strings.TrimPrefix(tmpDir, os.Getenv("HOMEDRIVE")))
} else {
os.Setenv("HOME", tmpDir)
}
flyrc = filepath.Join(userHomeDir(), ".flyrc")
flyFixtureFile, err := os.OpenFile("./fixtures/flyrc.yml", os.O_RDONLY, 0600)
Expect(err).NotTo(HaveOccurred())
flyFixtureData, err := ioutil.ReadAll(flyFixtureFile)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
Expect(err).NotTo(HaveOccurred())
createFlyRc(rc.Targets{
"test1": {
API: "https://example.com/test1",
TeamName: "main",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 1))},
},
"test2": {
API: "https://example.com/test2",
TeamName: "main",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 2))},
},
})
flyCmd := exec.Command(flyPath, "targets")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
@ -81,21 +63,15 @@ var _ = Describe("Fly CLI", func() {
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "test1"}, {Contents: "https://example.com/test1"}, {Contents: "main"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
},
}))
})
AfterEach(func() {
os.RemoveAll(tmpDir)
})
Context("when url configuration is specified", func() {
It("should update url field of target", func() {
flyCmd = exec.Command(flyPath, "-t", "test", "edit-target", "--concourse-url", "new-url")
flyCmd = exec.Command(flyPath, "-t", "test1", "edit-target", "--concourse-url", "new-url")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
@ -103,7 +79,7 @@ var _ = Describe("Fly CLI", func() {
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(gbytes.Say(`Updated target: test`))
Expect(sess.Out).To(gbytes.Say(`Updated target: test1`))
flyCmd = exec.Command(flyPath, "targets")
sess, err = gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
@ -118,10 +94,8 @@ var _ = Describe("Fly CLI", func() {
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "new-url"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "test1"}, {Contents: "new-url"}, {Contents: "main"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
},
}))
})
@ -129,7 +103,7 @@ var _ = Describe("Fly CLI", func() {
Context("when team name configuration is specified", func() {
It("should update team name of target", func() {
flyCmd = exec.Command(flyPath, "-t", "omt", "edit-target", "--team-name", "new-team")
flyCmd = exec.Command(flyPath, "-t", "test2", "edit-target", "--team-name", "new-team")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
@ -137,7 +111,7 @@ var _ = Describe("Fly CLI", func() {
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(gbytes.Say(`Updated target: omt`))
Expect(sess.Out).To(gbytes.Say(`Updated target: test2`))
flyCmd = exec.Command(flyPath, "targets")
sess, err = gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
@ -152,10 +126,8 @@ var _ = Describe("Fly CLI", func() {
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "new-team"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "test1"}, {Contents: "https://example.com/test1"}, {Contents: "main"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "new-team"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
},
}))
})
@ -163,7 +135,7 @@ var _ = Describe("Fly CLI", func() {
Context("when target name configuration is specified", func() {
It("should update the target name", func() {
flyCmd = exec.Command(flyPath, "-t", "another-test", "edit-target", "--target-name", "and-another-test")
flyCmd = exec.Command(flyPath, "-t", "test2", "edit-target", "--target-name", "new-target")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
@ -171,7 +143,7 @@ var _ = Describe("Fly CLI", func() {
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(gbytes.Say(`Updated target: another-test`))
Expect(sess.Out).To(gbytes.Say(`Updated target: test2`))
flyCmd = exec.Command(flyPath, "targets")
sess, err = gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
@ -186,10 +158,8 @@ var _ = Describe("Fly CLI", func() {
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "and-another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "new-target"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
{{Contents: "test1"}, {Contents: "https://example.com/test1"}, {Contents: "main"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
},
}))
})

View File

@ -1,7 +0,0 @@
targets:
test:
api: https://example.com/test
team: test
token:
type: Bearer
value: banana

View File

@ -1,20 +0,0 @@
targets:
test:
api: https://example.com/test
team: test
token:
type: Bearer
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNDU4OTQ4NTk3IiwiaXNBZG1pbiI6Im5vcGUiLCJ0ZWFtSUQiOjEsInRlYW1OYW1lIjoibWFpbiJ9.278HuhPsg5mU51ipDI2aVrhzIHfM-a8OcyQ5Us_0faw
another-test:
api: https://example.com/another-test
team: test
token:
type: Bearer
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNDU4MzUyNDcwIiwiaXNBZG1pbiI6Im5vcGUiLCJ0ZWFtSUQiOjEsInRlYW1OYW1lIjoibWFpbiJ9.v04hbwIFdMNjp6BCpz2jvOYNpAeBY8pio6hlXQizLAM
omt:
api: https://example.com/omt
token:
type: Bearer
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNDU4NTI1MjcwIiwiaXNBZG1pbiI6Im5vcGUiLCJ0ZWFtSUQiOjEsInRlYW1OYW1lIjoibWFpbiJ9.W14O2X3HpAt0s_aYeQ-WXqdzFhSzbdW7G-twpPSkBOA
no-token:
api: https://example.com/no-token

View File

@ -5,7 +5,6 @@ import (
"io"
"io/ioutil"
"log"
"os"
"os/exec"
. "github.com/onsi/ginkgo"
@ -142,7 +141,6 @@ var _ = Describe("login -k Command", func() {
Context("with --ca-cert", func() {
var (
tmpDir string
sslCert string
)
@ -165,11 +163,6 @@ var _ = Describe("login -k Command", func() {
tokenHandler(),
userInfoHandler(),
)
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).NotTo(HaveOccurred())
os.Setenv("HOME", tmpDir)
})
It("succeeds", func() {
@ -195,15 +188,14 @@ var _ = Describe("login -k Command", func() {
Context("to existing target with invalid SSL certificate", func() {
Context("when 'insecure' is not set", func() {
BeforeEach(func() {
flyrcContents := `targets:
some-target:
api: ` + loginATCServer.URL() + `
team: main
ca_cert: some-ca-cert
token:
type: Bearer
value: some-token`
ioutil.WriteFile(homeDir+"/.flyrc", []byte(flyrcContents), 0777)
createFlyRc(rc.Targets{
"some-target": {
API: loginATCServer.URL(),
TeamName: "main",
CACert: "some-ca-cert",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 1))},
},
})
})
Context("with -k", func() {

View File

@ -25,21 +25,8 @@ import (
var _ = Describe("login Command", func() {
var (
loginATCServer *ghttp.Server
tmpDir string
)
BeforeEach(func() {
var err error
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).ToNot(HaveOccurred())
os.Setenv("HOME", tmpDir)
})
AfterEach(func() {
os.RemoveAll(tmpDir)
})
Describe("login with no target name", func() {
var (
flyCmd *exec.Cmd

View File

@ -1,13 +1,9 @@
package integration_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"github.com/concourse/concourse/fly/rc"
"github.com/concourse/concourse/fly/ui"
"github.com/fatih/color"
@ -20,6 +16,40 @@ import (
var _ = Describe("logout Command", func() {
BeforeEach(func() {
createFlyRc(rc.Targets{
"test1": {
API: "https://example.com/test1",
TeamName: "main",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 1))},
},
"test2": {
API: "https://example.com/test2",
TeamName: "main",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 2))},
},
})
flyCmd := exec.Command(flyPath, "targets")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(sess).Should(gexec.Exit(0))
Expect(sess.Out).To(PrintTable(ui.Table{
Headers: ui.TableRow{
{Contents: "name", Color: color.New(color.Bold)},
{Contents: "url", Color: color.New(color.Bold)},
{Contents: "team", Color: color.New(color.Bold)},
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "test1"}, {Contents: "https://example.com/test1"}, {Contents: "main"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
},
}))
})
Describe("missing parameters", func() {
Context("when validating parameters", func() {
It("instructs the user to specify --target or --all if both are missing", func() {
@ -49,147 +79,50 @@ var _ = Describe("logout Command", func() {
})
Describe("delete all", func() {
var (
flyrc string
tmpDir string
)
It("removes all tokens and all targets remain in flyrc", func() {
flyCmd := exec.Command(flyPath, "logout", "--all")
BeforeEach(func() {
var err error
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).NotTo(HaveOccurred())
if runtime.GOOS == "windows" {
os.Setenv("USERPROFILE", tmpDir)
os.Setenv("HOMEPATH", strings.TrimPrefix(tmpDir, os.Getenv("HOMEDRIVE")))
} else {
os.Setenv("HOME", tmpDir)
}
flyrc = filepath.Join(userHomeDir(), ".flyrc")
flyFixtureFile, err := os.OpenFile("./fixtures/flyrc.yml", os.O_RDONLY, 0600)
Expect(err).NotTo(HaveOccurred())
flyFixtureData, err := ioutil.ReadAll(flyFixtureFile)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
Expect(err).NotTo(HaveOccurred())
flyCmd := exec.Command(flyPath, "targets")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(sess).Should(gexec.Exit(0))
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(gbytes.Say(`logged out of all targets`))
flyCmd = exec.Command(flyPath, "targets")
sess, err = gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(sess).Should(gexec.Exit(0))
Expect(sess.Out).To(PrintTable(ui.Table{
Headers: ui.TableRow{
{Contents: "name", Color: color.New(color.Bold)},
{Contents: "url", Color: color.New(color.Bold)},
{Contents: "team", Color: color.New(color.Bold)},
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "test1"}, {Contents: "https://example.com/test1"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "n/a"}},
},
}))
})
AfterEach(func() {
os.RemoveAll(tmpDir)
})
Context("when it is called", func() {
It("removes all tokens and all targets remain in flyrc", func() {
flyCmd := exec.Command(flyPath, "logout", "--all")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(gbytes.Say(`logged out of all targets`))
flyCmd = exec.Command(flyPath, "targets")
sess, err = gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(sess).Should(gexec.Exit(0))
Expect(sess.Out).To(PrintTable(ui.Table{
Headers: ui.TableRow{
{Contents: "name", Color: color.New(color.Bold)},
{Contents: "url", Color: color.New(color.Bold)},
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "n/a"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "n/a"}},
},
}))
})
})
})
Describe("delete one", func() {
var (
flyrc string
tmpDir string
)
It("removes token of the target and the target should remain in .flyrc", func() {
flyCmd := exec.Command(flyPath, "logout", "-t", "test2")
BeforeEach(func() {
var err error
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).NotTo(HaveOccurred())
if runtime.GOOS == "windows" {
os.Setenv("USERPROFILE", tmpDir)
os.Setenv("HOMEPATH", strings.TrimPrefix(tmpDir, os.Getenv("HOMEDRIVE")))
} else {
os.Setenv("HOME", tmpDir)
}
flyrc = filepath.Join(userHomeDir(), ".flyrc")
flyFixtureFile, err := os.OpenFile("./fixtures/flyrc.yml", os.O_RDONLY, 0600)
Expect(err).NotTo(HaveOccurred())
flyFixtureData, err := ioutil.ReadAll(flyFixtureFile)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
Expect(err).NotTo(HaveOccurred())
flyCmd := exec.Command(flyPath, "targets")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(sess).Should(gexec.Exit(0))
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(PrintTable(ui.Table{
Headers: ui.TableRow{
{Contents: "name", Color: color.New(color.Bold)},
{Contents: "url", Color: color.New(color.Bold)},
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
},
}))
})
Expect(sess.Out).To(gbytes.Say(`logged out of target: test2`))
AfterEach(func() {
flyCmd := exec.Command(flyPath, "targets")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
flyCmd = exec.Command(flyPath, "targets")
sess, err = gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(sess).Should(gexec.Exit(0))
@ -197,32 +130,13 @@ var _ = Describe("logout Command", func() {
Headers: ui.TableRow{
{Contents: "name", Color: color.New(color.Bold)},
{Contents: "url", Color: color.New(color.Bold)},
{Contents: "team", Color: color.New(color.Bold)},
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "test1"}, {Contents: "https://example.com/test1"}, {Contents: "main"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
{{Contents: "test2"}, {Contents: "https://example.com/test2"}, {Contents: "main"}, {Contents: "n/a"}},
},
}))
os.RemoveAll(tmpDir)
})
Context("when it is called", func() {
It("removes token of the target and the target should remain in .flyrc", func() {
flyCmd := exec.Command(flyPath, "logout", "-t", "omt")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(0))
Expect(sess.Out).To(gbytes.Say(`logged out of target: omt`))
})
})
})
})

View File

@ -1,11 +1,10 @@
package integration_test
import (
"io/ioutil"
"os"
"net/http"
"os/exec"
"path/filepath"
"github.com/concourse/concourse/fly/rc"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gbytes"
@ -15,56 +14,22 @@ import (
var _ = Describe("status Command", func() {
var (
tmpDir string
flyrc string
flyCmd *exec.Cmd
)
BeforeEach(func() {
var err error
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).ToNot(HaveOccurred())
os.Setenv("HOME", tmpDir)
flyrc = filepath.Join(userHomeDir(), ".flyrc")
flyFixtureData := []byte(`
targets:
another-test:
api: ` + atcServer.URL() + `
team: test
token:
type: Bearer
value: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxNDU4MzUyNDcwIiwiaXNBZG1pbiI6Im5vcGUiLCJ0ZWFtSUQiOjEsInRlYW1OYW1lIjoibWFpbiJ9.v04hbwIFdMNjp6BCpz2jvOYNpAeBY8pio6hlXQizLAM
bad-test:
api: https://example.com/another-test
team: test
token:
type: Bearer
value: bad-token
loggedout-test:
api: https://example.com/loggedout-test
team: test
token:
type: ""
value: ""
invalid-test:
api: https://example.com/invalid-test
team: test
token:
expired-test:
api: https://example.com/expired-test
team: test
token:
type: Bearer
value: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJjc3JmIjoiNGZlOGM1Y2VhYjFjNWFiMzE5MzMzNmQ2YThkOTE3OTJmZTA0YmEzZjg5Y2IwZDg0MTkzN2I2MzkzYTdhYTg2MyIsImV4cCI6MTUyMTMwODk2MCwiaXNBZG1pbiI6dHJ1ZSwidGVhbU5hbWUiOiJtYWluIn0.oyb-2CPLnXy-7S-9FWWlx106KI5Xpd6B5XIrFOvcG1yyh5nrGpM4NfgaW7ugN4zzi2mSFGawRlkulzgAZ4RxAEdTOnlSXvVZO3vD70sMlrp_LX-lYaqJ7XXVXNKvKE_74YGZY414TYVy2IxL-4Qf7pbb0uGDky03jQFxkWVSUiD5iLwaqpvxpHTEuVNoZc9a8YNiOdETvqnt50drsmxpkblM60DrWuDVPifOfTrooSMxULnl3pYXDsTPZbrc6QVLA_Hpi7wWCNEZbAojTQ3taIwzp7BBAuxUNcVMpJKy3Um5oMHcibe1R0PsZ0J49PbLSclZfhJ7wjHBc7FQEKTZzQ
`)
err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
os.RemoveAll(tmpDir)
createFlyRc(rc.Targets{
"with-token": {
API: atcServer.URL(),
TeamName: "test",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 1))},
},
"without-token": {
API: "https://example.com/another-test",
TeamName: "test",
Token: &rc.TargetToken{},
},
})
})
Context("status with no target name", func() {
@ -98,8 +63,8 @@ targets:
)
})
It("command exist with 0", func() {
flyCmd = exec.Command(flyPath, "-t", "another-test", "status")
It("the command succeeds", func() {
flyCmd = exec.Command(flyPath, "-t", "with-token", "status")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
@ -110,19 +75,19 @@ targets:
})
})
Context("when target is saved with valid token but is unauthorized on server", func() {
Context("when target is saved with a token that is rejected by the server", func() {
BeforeEach(func() {
atcServer.Reset()
atcServer.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("GET", "/api/v1/user"),
ghttp.RespondWith(401, nil),
ghttp.RespondWith(http.StatusUnauthorized, nil),
),
)
})
It("command exist with 1", func() {
flyCmd = exec.Command(flyPath, "-t", "another-test", "status")
It("the command fails", func() {
flyCmd = exec.Command(flyPath, "-t", "with-token", "status")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
@ -130,73 +95,21 @@ targets:
Expect(sess.ExitCode()).To(Equal(1))
Expect(sess.Err).To(gbytes.Say(`please login again`))
Expect(sess.Err).To(gbytes.Say(`token validation failed with error : not authorized`))
Expect(sess.Err).To(gbytes.Say(`token validation failed with error: not authorized`))
})
})
Context("when target is saved with invalid token", func() {
It("command exist with 1", func() {
flyCmd = exec.Command(flyPath, "-t", "bad-test", "status")
It("the command fails", func() {
flyCmd = exec.Command(flyPath, "-t", "without-token", "status")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(1))
Expect(sess.Err).To(gbytes.Say(`please login again`))
Expect(sess.Err).To(gbytes.Say(`token validation failed with error : token contains an invalid number of segments`))
})
})
Context("when target is saved with expired token", func() {
It("command exist with 1", func() {
flyCmd = exec.Command(flyPath, "-t", "expired-test", "status")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(1))
Expect(sess.Err).To(gbytes.Say(`please login again`))
Expect(sess.Err).To(gbytes.Say(`token validation failed with error : Token is expired`))
})
})
Context("when target is logged out", func() {
It("command exist with 1 and log out msg", func() {
flyCmd = exec.Command(flyPath, "-t", "loggedout-test", "status")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(1))
Expect(sess.Err).To(gbytes.Say(`logged out`))
})
})
Context("when invalid token is in target", func() {
It("command exist with 1", func() {
flyCmd = exec.Command(flyPath, "-t", "invalid-test", "status")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(1))
Expect(sess.Err).To(gbytes.Say(`logged out`))
})
})
Context("when unknown target is used", func() {
It("command exist with 1", func() {
flyCmd = exec.Command(flyPath, "-t", "unknown-test", "status")
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
<-sess.Exited
Expect(sess.ExitCode()).To(Equal(1))
Expect(sess.Err).To(gbytes.Say(`unknown target: unknown-test`))
})
})
})
})

View File

@ -1,21 +1,27 @@
package integration_test
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
"time"
"github.com/concourse/concourse/atc"
"github.com/concourse/concourse/atc/db"
"github.com/concourse/concourse/fly/rc"
"github.com/concourse/concourse/skymarshal/token"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
"github.com/onsi/gomega/ghttp"
"gopkg.in/square/go-jose.v2/jwt"
)
var flyPath string
@ -67,7 +73,7 @@ func tokenHandler() http.HandlerFunc {
ghttp.VerifyRequest("POST", "/sky/issuer/token"),
ghttp.RespondWithJSONEncoded(
200,
token(),
oauthToken(),
),
)
}
@ -86,14 +92,42 @@ func userInfoHandler() http.HandlerFunc {
)
}
func token() map[string]string {
func validAccessToken(expiry time.Time) string {
accessToken, err := token.Factory{}.GenerateAccessToken(db.Claims{
Claims: jwt.Claims{Expiry: jwt.NewNumericDate(expiry)}},
)
if err != nil {
panic(err)
}
return accessToken
}
func oauthToken() map[string]string {
return map[string]string{
"token_type": "Bearer",
"access_token": "some-access-token",
"access_token": validAccessToken(time.Now()),
"id_token": "some-token",
}
}
func date(year int, month time.Month, day int) time.Time {
return time.Date(year, month, day, 0, 0, 0, 0, time.UTC)
}
func createFlyRc(targets rc.Targets) {
flyrc := filepath.Join(homeDir, ".flyrc")
flyrcBytes, err := json.Marshal(rc.RC{Targets: targets})
if err != nil {
panic(err)
}
err = ioutil.WriteFile(flyrc, flyrcBytes, 0600)
if err != nil {
panic(err)
}
}
var _ = BeforeEach(func() {
atcServer = ghttp.NewServer()

View File

@ -1,11 +1,9 @@
package integration_test
import (
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"github.com/concourse/concourse/fly/rc"
"github.com/concourse/concourse/fly/ui"
"github.com/fatih/color"
"github.com/onsi/gomega/gbytes"
@ -17,38 +15,39 @@ import (
var _ = Describe("Fly CLI", func() {
var (
flyCmd *exec.Cmd
flyrc string
tmpDir string
flyrcFixture string
flyCmd *exec.Cmd
targets rc.Targets
)
JustBeforeEach(func() {
var err error
tmpDir, err = ioutil.TempDir("", "fly-test")
Expect(err).NotTo(HaveOccurred())
os.Setenv("HOME", tmpDir)
flyrc = filepath.Join(userHomeDir(), ".flyrc")
flyFixtureFile, err := os.OpenFile(flyrcFixture, os.O_RDONLY, 0600)
Expect(err).NotTo(HaveOccurred())
flyFixtureData, err := ioutil.ReadAll(flyFixtureFile)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(flyrc, flyFixtureData, 0600)
Expect(err).NotTo(HaveOccurred())
createFlyRc(targets)
flyCmd = exec.Command(flyPath, "targets")
})
BeforeEach(func() {
flyrcFixture = "./fixtures/flyrc.yml"
})
AfterEach(func() {
os.RemoveAll(tmpDir)
targets = rc.Targets{
"another-test": {
API: "https://example.com/another-test",
TeamName: "test",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 1))},
},
"no-token": {
API: "https://example.com/no-token",
TeamName: "main",
Token: nil,
},
"omt": {
API: "https://example.com/omt",
TeamName: "main",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 2))},
},
"test": {
API: "https://example.com/test",
TeamName: "test",
Token: &rc.TargetToken{Type: "Bearer", Value: validAccessToken(date(2020, 1, 3))},
},
}
})
Describe("targets", func() {
@ -67,10 +66,10 @@ var _ = Describe("Fly CLI", func() {
{Contents: "expiry", Color: color.New(color.Bold)},
},
Data: []ui.TableRow{
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Sat, 19 Mar 2016 01:54:30 UTC"}},
{{Contents: "another-test"}, {Contents: "https://example.com/another-test"}, {Contents: "test"}, {Contents: "Wed, 01 Jan 2020 00:00:00 UTC"}},
{{Contents: "no-token"}, {Contents: "https://example.com/no-token"}, {Contents: "main"}, {Contents: "n/a"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Mon, 21 Mar 2016 01:54:30 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 25 Mar 2016 23:29:57 UTC"}},
{{Contents: "omt"}, {Contents: "https://example.com/omt"}, {Contents: "main"}, {Contents: "Thu, 02 Jan 2020 00:00:00 UTC"}},
{{Contents: "test"}, {Contents: "https://example.com/test"}, {Contents: "test"}, {Contents: "Fri, 03 Jan 2020 00:00:00 UTC"}},
},
}))
})
@ -78,22 +77,27 @@ var _ = Describe("Fly CLI", func() {
Context("when the .flyrc contains a target with an invalid token", func() {
BeforeEach(func() {
flyrcFixture = "./fixtures/flyrc-badtoken.yml"
targets = rc.Targets{
"test": {
API: "https://example.com/test",
Token: &rc.TargetToken{Type: "Bearer", Value: "banana"},
},
}
})
It("shows error message from jwt parsing library but does not fail", func() {
It("indicates the token is invalid", func() {
sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(sess).Should(gexec.Exit(0))
Expect(sess).Should(gbytes.Say("n/a: token contains an invalid number of segments"))
Expect(sess).Should(gbytes.Say("n/a: invalid token"))
})
})
Context("when no targets are available", func() {
BeforeEach(func() {
os.RemoveAll(flyrc)
createFlyRc(nil)
})
It("prints an empty table", func() {

View File

@ -101,7 +101,7 @@ func LoadTargetFromURL(url, team string, tracing bool) (Target, TargetName, erro
return nil, "", err
}
for name, props := range flyTargets.Targets {
for name, props := range flyTargets {
if props.API == url && props.TeamName == team {
target, err := LoadTarget(name, tracing)
return target, name, err

View File

@ -21,7 +21,7 @@ func (name *TargetName) Complete(match string) []flags.Completion {
}
names := []string{}
for name := range flyTargets.Targets {
for name := range flyTargets {
if strings.HasPrefix(string(name), match) {
names = append(names, string(name))
}

View File

@ -26,6 +26,12 @@ func (err UnknownTargetError) Error() string {
return fmt.Sprintf("unknown target: %s", err.TargetName)
}
type Targets map[TargetName]TargetProps
type RC struct {
Targets Targets `json:"targets"`
}
type TargetProps struct {
API string `json:"api"`
TeamName string `json:"team"`
@ -39,10 +45,6 @@ type TargetToken struct {
Value string `json:"value"`
}
type targetDetailsYAML struct {
Targets map[TargetName]TargetProps `json:"targets"`
}
func flyrcPath() string {
return filepath.Join(userHomeDir(), ".flyrc")
}
@ -53,7 +55,7 @@ func LogoutTarget(targetName TargetName) error {
return err
}
if target, ok := flyTargets.Targets[targetName]; ok {
if target, ok := flyTargets[targetName]; ok {
if target.Token != nil {
*target.Token = TargetToken{}
}
@ -68,13 +70,13 @@ func DeleteTarget(targetName TargetName) error {
return err
}
delete(flyTargets.Targets, targetName)
delete(flyTargets, targetName)
return writeTargets(flyrcPath(), flyTargets)
}
func DeleteAllTargets() error {
return writeTargets(flyrcPath(), &targetDetailsYAML{})
return writeTargets(flyrcPath(), Targets{})
}
func UpdateTargetProps(targetName TargetName, targetProps TargetProps) error {
@ -83,7 +85,7 @@ func UpdateTargetProps(targetName TargetName, targetProps TargetProps) error {
return err
}
target := flyTargets.Targets[targetName]
target := flyTargets[targetName]
if targetProps.API != "" {
target.API = targetProps.API
@ -93,7 +95,7 @@ func UpdateTargetProps(targetName TargetName, targetProps TargetProps) error {
target.TeamName = targetProps.TeamName
}
flyTargets.Targets[targetName] = target
flyTargets[targetName] = target
return writeTargets(flyrcPath(), flyTargets)
}
@ -105,8 +107,8 @@ func UpdateTargetName(targetName TargetName, newTargetName TargetName) error {
}
if newTargetName != "" {
flyTargets.Targets[newTargetName] = flyTargets.Targets[targetName]
delete(flyTargets.Targets, targetName)
flyTargets[newTargetName] = flyTargets[targetName]
delete(flyTargets, targetName)
}
return writeTargets(flyrcPath(), flyTargets)
@ -126,14 +128,14 @@ func SaveTarget(
}
flyrc := flyrcPath()
newInfo := flyTargets.Targets[targetName]
newInfo := flyTargets[targetName]
newInfo.API = api
newInfo.Insecure = insecure
newInfo.Token = token
newInfo.TeamName = teamName
newInfo.CACert = caCert
flyTargets.Targets[targetName] = newInfo
flyTargets[targetName] = newInfo
return writeTargets(flyrc, flyTargets)
}
@ -146,7 +148,7 @@ func selectTarget(selectedTarget TargetName) (TargetProps, error) {
return TargetProps{}, err
}
target, ok := flyTargets.Targets[selectedTarget]
target, ok := flyTargets[selectedTarget]
if !ok {
return TargetProps{}, UnknownTargetError{selectedTarget}
}
@ -174,8 +176,8 @@ func userHomeDir() string {
panic("could not detect home directory for .flyrc")
}
func LoadTargets() (*targetDetailsYAML, error) {
var flyTargets targetDetailsYAML
func LoadTargets() (Targets, error) {
var rc RC
flyrc := flyrcPath()
if _, err := os.Stat(flyrc); err == nil {
@ -183,28 +185,29 @@ func LoadTargets() (*targetDetailsYAML, error) {
if err != nil {
return nil, err
}
err = yaml.Unmarshal(flyTargetsBytes, &flyTargets)
err = yaml.Unmarshal(flyTargetsBytes, &rc)
if err != nil {
return nil, fmt.Errorf("in the file '%s': %s", flyrc, err)
}
}
if flyTargets.Targets == nil {
flyTargets.Targets = map[TargetName]TargetProps{}
targets := rc.Targets
if targets == nil {
targets = map[TargetName]TargetProps{}
}
for name, targetProps := range flyTargets.Targets {
for name, targetProps := range targets {
if targetProps.TeamName == "" {
targetProps.TeamName = atc.DefaultTeamName
flyTargets.Targets[name] = targetProps
targets[name] = targetProps
}
}
return &flyTargets, nil
return targets, nil
}
func writeTargets(configFileLocation string, targetsToWrite *targetDetailsYAML) error {
yamlBytes, err := yaml.Marshal(targetsToWrite)
func writeTargets(configFileLocation string, targetsToWrite Targets) error {
yamlBytes, err := yaml.Marshal(RC{Targets: targetsToWrite})
if err != nil {
return err
}

View File

@ -45,7 +45,7 @@ var _ = Describe("Targets", func() {
It("loads target with default team", func() {
targets, err := rc.LoadTargets()
Expect(err).ToNot(HaveOccurred())
Expect(targets.Targets).To(Equal(map[rc.TargetName]rc.TargetProps{
Expect(targets).To(Equal(rc.Targets{
"some-target": {
API: "http://concourse.com",
TeamName: atc.DefaultTeamName,
@ -85,7 +85,7 @@ var _ = Describe("Targets", func() {
It("should delete target from flyrc", func() {
returnedTargets, err := rc.LoadTargets()
Expect(err).ToNot(HaveOccurred())
Expect(returnedTargets.Targets).To(Equal(map[rc.TargetName]rc.TargetProps{
Expect(returnedTargets).To(Equal(rc.Targets{
"new-target": {
API: "some-api",
TeamName: "another-team",
@ -106,7 +106,7 @@ var _ = Describe("Targets", func() {
It("should delete all targets from flyrc", func() {
returnedTargets, err := rc.LoadTargets()
Expect(err).ToNot(HaveOccurred())
Expect(returnedTargets.Targets).To(Equal(map[rc.TargetName]rc.TargetProps{}))
Expect(returnedTargets).To(Equal(rc.Targets{}))
})
})
})
@ -134,7 +134,7 @@ var _ = Describe("Targets", func() {
targets, err := rc.LoadTargets()
Expect(err).ToNot(HaveOccurred())
Expect(targets.Targets).To(Equal(map[rc.TargetName]rc.TargetProps{
Expect(targets).To(Equal(rc.Targets{
"some-target": {
API: "new-api",
TeamName: "other-team",
@ -154,7 +154,7 @@ var _ = Describe("Targets", func() {
targets, err := rc.LoadTargets()
Expect(err).ToNot(HaveOccurred())
Expect(targets.Targets).To(Equal(map[rc.TargetName]rc.TargetProps{
Expect(targets).To(Equal(rc.Targets{
"some-other-target": {
API: "http://concourse.com",
TeamName: "main",

View File

@ -128,6 +128,7 @@ func (client *client) FindTeam(teamName string) (Team, error) {
if err != nil {
return nil, err
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusOK:

View File

@ -1,6 +1,8 @@
package concourse
import (
"encoding/json"
"io/ioutil"
"net/http"
"github.com/concourse/concourse/atc"
@ -8,17 +10,31 @@ import (
)
func (client *client) UserInfo() (atc.UserInfo, error) {
var connection = client.connection
resp, err := client.httpAgent.Send(internal.Request{
RequestName: atc.GetUser,
})
req, err := http.NewRequest("GET", connection.URL()+"/api/v1/user", nil)
if err != nil {
return atc.UserInfo{}, err
}
defer resp.Body.Close()
var userInfo atc.UserInfo
err = connection.SendHTTPRequest(req, false, &internal.Response{
Result: &userInfo,
})
return userInfo, err
switch resp.StatusCode {
case http.StatusOK:
var userInfo atc.UserInfo
err = json.NewDecoder(resp.Body).Decode(&userInfo)
if err != nil {
return atc.UserInfo{}, err
}
return userInfo, nil
case http.StatusUnauthorized:
return atc.UserInfo{}, ErrUnauthorized
default:
body, _ := ioutil.ReadAll(resp.Body)
return atc.UserInfo{}, internal.UnexpectedResponseError{
StatusCode: resp.StatusCode,
Status: resp.Status,
Body: string(body),
}
}
}

1
go.mod
View File

@ -36,7 +36,6 @@ require (
github.com/cppforlife/go-semi-semantic v0.0.0-20160921010311-576b6af77ae4
github.com/creack/pty v1.1.9 // indirect
github.com/cyberark/conjur-api-go v0.6.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/evanphx/json-patch v4.5.0+incompatible // indirect