Skip to content

Commit

Permalink
Merge pull request #67 from CircleCI-Public/split-host-endpoint
Browse files Browse the repository at this point in the history
CLI should use host instead of asking user for endpoint
  • Loading branch information
Zachary Scott authored Aug 20, 2018
2 parents 14d2108 + aeaa607 commit de70cdc
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 45 deletions.
86 changes: 72 additions & 14 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"context"
"io/ioutil"
"net/url"
"os"
"strings"

Expand Down Expand Up @@ -77,6 +78,31 @@ func (response GQLResponseErrors) ToError() error {
return errors.New(strings.Join(messages, ": "))
}

// GraphQLServerAddress returns the full address to CircleCI GraphQL API server
func GraphQLServerAddress() (string, error) {
// 1. Parse the endpoint
endpoint, err := url.Parse(viper.GetString("endpoint"))
if err != nil {
return endpoint.String(), errors.Wrapf(err, "Parsing endpoint '%s'", viper.GetString("endpoint"))
}

// 2. Parse the host
host, err := url.Parse(viper.GetString("host"))
if err != nil {
return host.String(), errors.Wrapf(err, "Parsing host '%s'", viper.GetString("host"))
}

// 3. Resolve the two URLs using host as the base
// We use ResolveReference which has specific behavior we can rely for
// older configurations which included the absolute path for the endpoint flag.
//
// https://golang.org/pkg/net/url/#URL.ResolveReference
//
// Specifically this function always returns the reference (endpoint) if provided an absolute URL.
// This way we can safely introduce --host and merge the two.
return host.ResolveReference(endpoint).String(), err
}

// nolint: gosec
func loadYaml(path string) (string, error) {
var err error
Expand All @@ -102,7 +128,11 @@ func buildAndOrbQuery(ctx context.Context, logger *logger.Logger, configPath str

request := client.NewAuthorizedRequest(viper.GetString("token"), query)
request.Var("config", config)
graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return err
}
graphQLclient := client.NewClient(address, logger)

err = graphQLclient.Run(ctx, request, response)

Expand Down Expand Up @@ -190,7 +220,11 @@ func OrbPublish(ctx context.Context, logger *logger.Logger,
request.Var("orbId", orbID)
request.Var("version", orbVersion)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return nil, err
}
graphQLclient := client.NewClient(address, logger)

err = graphQLclient.Run(ctx, request, &response)

Expand All @@ -216,9 +250,13 @@ func getOrbID(ctx context.Context, logger *logger.Logger, name string) (string,
request := client.NewAuthorizedRequest(viper.GetString("token"), query)
request.Var("name", name)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return "", err
}
graphQLclient := client.NewClient(address, logger)

err := graphQLclient.Run(ctx, request, &response)
err = graphQLclient.Run(ctx, request, &response)

if err != nil {
return "", err
Expand Down Expand Up @@ -258,9 +296,13 @@ func createNamespaceWithOwnerID(ctx context.Context, logger *logger.Logger, name
request.Var("name", name)
request.Var("organizationId", ownerID)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return nil, err
}
graphQLclient := client.NewClient(address, logger)

err := graphQLclient.Run(ctx, request, &response)
err = graphQLclient.Run(ctx, request, &response)

if err != nil {
err = errors.Wrap(err, fmt.Sprintf("Unable to create namespace %s for ownerId %s", name, ownerID))
Expand Down Expand Up @@ -290,9 +332,13 @@ func getOrganization(ctx context.Context, logger *logger.Logger, organizationNam
request.Var("organizationName", organizationName)
request.Var("organizationVcs", organizationVcs)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return "", err
}
graphQLclient := client.NewClient(address, logger)

err := graphQLclient.Run(ctx, request, &response)
err = graphQLclient.Run(ctx, request, &response)

if err != nil {
err = errors.Wrapf(err, "Unable to find organization %s of vcs-type %s", organizationName, organizationVcs)
Expand Down Expand Up @@ -337,9 +383,13 @@ func getNamespace(ctx context.Context, logger *logger.Logger, name string) (stri
request := client.NewAuthorizedRequest(viper.GetString("token"), query)
request.Var("name", name)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return "", err
}
graphQLclient := client.NewClient(address, logger)

err := graphQLclient.Run(ctx, request, &response)
err = graphQLclient.Run(ctx, request, &response)

if err != nil {
err = errors.Wrapf(err, "Unable to find namespace %s", name)
Expand Down Expand Up @@ -376,9 +426,13 @@ func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string,
request.Var("name", name)
request.Var("registryNamespaceId", namespaceID)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return nil, err
}
graphQLclient := client.NewClient(address, logger)

err := graphQLclient.Run(ctx, request, &response)
err = graphQLclient.Run(ctx, request, &response)

if err != nil {
err = errors.Wrapf(err, "Unable to create orb %s for namespaceID %s", name, namespaceID)
Expand Down Expand Up @@ -422,9 +476,13 @@ func OrbSource(ctx context.Context, logger *logger.Logger, namespace string, orb
request := client.NewAuthorizedRequest(viper.GetString("token"), query)
request.Var("name", name)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)
address, err := GraphQLServerAddress()
if err != nil {
return "", err
}
graphQLclient := client.NewClient(address, logger)

err := graphQLclient.Run(ctx, request, &response)
err = graphQLclient.Run(ctx, request, &response)

if err != nil {
return "", err
Expand Down
2 changes: 1 addition & 1 deletion cmd/cmd_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func appendPostHandler(server *ghttp.Server, authToken string, combineHandlers .
for _, handler := range combineHandlers {
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/"),
ghttp.VerifyRequest("POST", "/graphql-unstable"),
ghttp.VerifyHeader(http.Header{
"Authorization": []string{authToken},
}),
Expand Down
3 changes: 1 addition & 2 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ func newConfigCommand() *cobra.Command {
}
validateCommand.Annotations["PATH"] = configAnnotations["PATH"]
validateCommand.PersistentFlags().StringVarP(&configPath, "config", "c", ".circleci/config.yml", "path to config file")
err := validateCommand.PersistentFlags().MarkHidden("config")
if err != nil {
if err := validateCommand.PersistentFlags().MarkHidden("config"); err != nil {
panic(err)
}

Expand Down
4 changes: 2 additions & 2 deletions cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ var _ = Describe("Config", func() {
command = exec.Command(pathCLI,
"config", "validate",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
config.Path,
)
})
Expand Down Expand Up @@ -134,7 +134,7 @@ var _ = Describe("Config", func() {
command = exec.Command(pathCLI,
"config", "process",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
config.Path,
)
})
Expand Down
9 changes: 7 additions & 2 deletions cmd/diagnostic.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
"github.com/CircleCI-Public/circleci-cli/api"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand All @@ -17,13 +18,17 @@ func newDiagnosticCommand() *cobra.Command {
}

func diagnostic(cmd *cobra.Command, args []string) error {
endpoint := viper.GetString("endpoint")
address, err := api.GraphQLServerAddress()
if err != nil {
return err
}

token := viper.GetString("token")

Logger.Infoln("\n---\nCircleCI CLI Diagnostics\n---\n")
Logger.Infof("Config found: %v\n", viper.ConfigFileUsed())

Logger.Infof("GraphQL API endpoint: %s\n", endpoint)
Logger.Infof("GraphQL API address: %s\n", address)

if token == "token" || token == "" {
return errors.New("please set a token")
Expand Down
66 changes: 64 additions & 2 deletions cmd/diagnostic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,69 @@ token: mytoken
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Err.Contents()).Should(BeEmpty())
Eventually(session.Out).Should(gbytes.Say("GraphQL API endpoint: https://example.com/graphql"))
Eventually(session.Out).Should(gbytes.Say("GraphQL API address: https://example.com/graphql"))
Eventually(session.Out).Should(gbytes.Say("OK, got a token."))
Eventually(session).Should(gexec.Exit(0))
})
})

Describe("token, host, and old endpoint set in config file", func() {
BeforeEach(func() {
_, err := config.Write([]byte(`
endpoint: https://example.com/graphql
host: https://circleci.com/
token: mytoken
`))
Expect(err).ToNot(HaveOccurred())
Expect(config.Close()).To(Succeed())
})

It("print success", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Err.Contents()).Should(BeEmpty())
Eventually(session.Out).Should(gbytes.Say("GraphQL API address: https://example.com/graphql"))
Eventually(session.Out).Should(gbytes.Say("OK, got a token."))
Eventually(session).Should(gexec.Exit(0))
})
})

Describe("token, host, and new endpoint set in config file", func() {
BeforeEach(func() {
_, err := config.Write([]byte(`
endpoint: graphql
host: https://circleci.com/
token: mytoken
`))
Expect(err).ToNot(HaveOccurred())
Expect(config.Close()).To(Succeed())
})

It("print success", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Err.Contents()).Should(BeEmpty())
Eventually(session.Out).Should(gbytes.Say("GraphQL API address: https://circleci.com/graphql"))
Eventually(session.Out).Should(gbytes.Say("OK, got a token."))
Eventually(session).Should(gexec.Exit(0))
})
})

Describe("token, host, and missing endpoint set in config file", func() {
BeforeEach(func() {
_, err := config.Write([]byte(`
host: https://circleci.com/
token: mytoken
`))
Expect(err).ToNot(HaveOccurred())
Expect(config.Close()).To(Succeed())
})

It("print success", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Err.Contents()).Should(BeEmpty())
Eventually(session.Out).Should(gbytes.Say("GraphQL API address: https://circleci.com/graphql-unstable"))
Eventually(session.Out).Should(gbytes.Say("OK, got a token."))
Eventually(session).Should(gexec.Exit(0))
})
Expand All @@ -88,7 +150,7 @@ token:
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())
Eventually(session.Err).Should(gbytes.Say("Error: please set a token"))
Eventually(session.Out).Should(gbytes.Say("GraphQL API endpoint: https://example.com/graphql"))
Eventually(session.Out).Should(gbytes.Say("GraphQL API address: https://example.com/graphql"))
Eventually(session).Should(gexec.Exit(255))
})
})
Expand Down
4 changes: 2 additions & 2 deletions cmd/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var _ = Describe("Namespace integration tests", func() {
command = exec.Command(pathCLI,
"namespace", "create",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
"foo-ns",
"BITBUCKET",
"test-org",
Expand Down Expand Up @@ -96,7 +96,7 @@ var _ = Describe("Namespace integration tests", func() {
command = exec.Command(pathCLI,
"namespace", "create",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
"foo-ns",
"BITBUCKET",
"test-org",
Expand Down
7 changes: 5 additions & 2 deletions cmd/orb.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/machinebox/graphql"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"gopkg.in/yaml.v2"
)

Expand Down Expand Up @@ -190,7 +189,11 @@ query ListOrbs ($after: String!) {
}
`)

client := client.NewClient(viper.GetString("endpoint"), Logger)
address, err := api.GraphQLServerAddress()
if err != nil {
return err
}
client := client.NewClient(address, Logger)

var result orbList
currentCursor := ""
Expand Down
12 changes: 6 additions & 6 deletions cmd/orb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var _ = Describe("Orb integration tests", func() {
command = exec.Command(pathCLI,
"orb", "validate",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
"-",
)
stdin, err := command.StdinPipe()
Expand Down Expand Up @@ -118,7 +118,7 @@ var _ = Describe("Orb integration tests", func() {
command = exec.Command(pathCLI,
"orb", "validate", orb.Path,
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
)
})

Expand Down Expand Up @@ -167,7 +167,7 @@ var _ = Describe("Orb integration tests", func() {
command = exec.Command(pathCLI,
"orb", "validate", orb.Path,
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
)
})

Expand Down Expand Up @@ -247,7 +247,7 @@ var _ = Describe("Orb integration tests", func() {
command = exec.Command(pathCLI,
"orb", "process",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
orb.Path,
)
})
Expand Down Expand Up @@ -330,7 +330,7 @@ var _ = Describe("Orb integration tests", func() {
command = exec.Command(pathCLI,
"orb", "publish", "release",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
orb.Path,
"my",
"orb",
Expand Down Expand Up @@ -457,7 +457,7 @@ var _ = Describe("Orb integration tests", func() {
command = exec.Command(pathCLI,
"orb", "create",
"--token", token,
"--endpoint", testServer.URL(),
"--host", testServer.URL(),
"bar-ns", "foo-orb",
)
})
Expand Down
Loading

0 comments on commit de70cdc

Please sign in to comment.