Skip to content

Commit

Permalink
Merge pull request #32 from CircleCI-Public/create-namespace
Browse files Browse the repository at this point in the history
Create orb
  • Loading branch information
Zachary Scott authored Jul 25, 2018
2 parents 41b2030 + 08bddb8 commit 0357eb2
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 31 deletions.
5 changes: 4 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@ jobs:

lint:
docker:
- image: supinf/gometalinter:latest
# TODO: use this image once it updates latest gometalinter
#- image: supinf/gometalinter:latest
- image: circleci/golang:1.10
working_directory: /go/src/github.com/CircleCI-Public/circleci-cli
environment:
CGO_ENABLED: 0
steps:
- checkout
- run: make dev
- run: gometalinter ./...

deploy:
Expand Down
2 changes: 1 addition & 1 deletion .gometalinter.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
"Enable": [
"deadcode",
"errcheck",
"gas",
"goconst",
"gocyclo",
"gofmt",
"goimports",
"golint",
"gosec",
"gosimple",
"gotype",
"gotypex",
Expand Down
103 changes: 97 additions & 6 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ type CreateNamespaceResponse struct {
GQLResponseErrors
}

// CreateOrbResponse type matches the data shape of the GQL response for
// creating an orb
type CreateOrbResponse struct {
Orb struct {
ID string
}

GQLResponseErrors
}

// ToError returns all GraphQL errors for a single response concatenated, or
// nil.
func (response GQLResponseErrors) ToError() error {
Expand All @@ -67,6 +77,7 @@ func (response GQLResponseErrors) ToError() error {
return errors.New(strings.Join(messages, ": "))
}

// nolint: gosec
func loadYaml(path string) (string, error) {
var err error
var config []byte
Expand Down Expand Up @@ -162,7 +173,6 @@ func OrbPublish(ctx context.Context, logger *logger.Logger,
) {
orb {
version
createdAt
}
errors { message }
}
Expand All @@ -184,7 +194,7 @@ func OrbPublish(ctx context.Context, logger *logger.Logger,
return &response.PublishOrb.PublishOrbResponse, err
}

func createNamespaceByID(ctx context.Context, logger *logger.Logger, name string, ownerID string) (*CreateNamespaceResponse, error) {
func createNamespaceWithOwnerID(ctx context.Context, logger *logger.Logger, name string, ownerID string) (*CreateNamespaceResponse, error) {
var response struct {
CreateNamespace struct {
CreateNamespaceResponse
Expand All @@ -198,7 +208,6 @@ func createNamespaceByID(ctx context.Context, logger *logger.Logger, name string
organizationId: $organizationId
) {
namespace {
createdAt
id
}
errors {
Expand Down Expand Up @@ -248,8 +257,10 @@ func getOrganization(ctx context.Context, logger *logger.Logger, organizationNam

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

if err != nil || response.Organization.ID == "" {
err = errors.Wrap(err, fmt.Sprintf("Unable to find organization %s of vcs-type %s", organizationName, organizationVcs))
if err != nil {
err = errors.Wrapf(err, "Unable to find organization %s of vcs-type %s", organizationName, organizationVcs)
} else if response.Organization.ID == "" {
err = fmt.Errorf("Unable to find organization %s of vcs-type %s", organizationName, organizationVcs)
}

return response.Organization.ID, err
Expand All @@ -262,11 +273,91 @@ func CreateNamespace(ctx context.Context, logger *logger.Logger, name string, or
return nil, err
}

namespace, err := createNamespaceByID(ctx, logger, name, organizationID)
namespace, err := createNamespaceWithOwnerID(ctx, logger, name, organizationID)

if err != nil {
return nil, err
}

return namespace, err
}

func getNamespace(ctx context.Context, logger *logger.Logger, name string) (string, error) {
var response struct {
RegistryNamespace struct {
ID string
}
}

query := `
query($name: String!) {
registryNamespace(
name: $name
){
id
}
}`
request := client.NewAuthorizedRequest(viper.GetString("token"), query)
request.Var("name", name)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)

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

if err != nil {
err = errors.Wrapf(err, "Unable to find namespace %s", name)
} else if response.RegistryNamespace.ID == "" {
err = fmt.Errorf("Unable to find namespace %s", name)
}

return response.RegistryNamespace.ID, err
}

func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, namespaceID string) (*CreateOrbResponse, error) {
var response struct {
CreateOrb struct {
CreateOrbResponse
}
}

query := `mutation($name: String!, $registryNamespaceId: UUID!){
createOrb(
name: $name,
registryNamespaceId: $registryNamespaceId
){
orb {
id
}
errors {
message
type
}
}
}`

request := client.NewAuthorizedRequest(viper.GetString("token"), query)
request.Var("name", name)
request.Var("registryNamespaceId", namespaceID)

graphQLclient := client.NewClient(viper.GetString("endpoint"), logger)

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

if err != nil {
err = errors.Wrapf(err, "Unable to create orb %s for namespaceID %s", name, namespaceID)
}

return &response.CreateOrb.CreateOrbResponse, err
}

// CreateOrb creates (reserves) an orb within a namespace
func CreateOrb(ctx context.Context, logger *logger.Logger, name string, namespace string) (*CreateOrbResponse, error) {
namespaceID, err := getNamespace(ctx, logger, namespace)

if err != nil {
return nil, err
}

orb, err := createOrbWithNsID(ctx, logger, name, namespaceID)
return orb, err
}
2 changes: 1 addition & 1 deletion cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func findLatestPicardSha() (string, error) {
latest := sha256.FindString(output)

if latest == "" {
return "", errors.New("failed to parse sha256 from docker pull output")
return "", fmt.Errorf("failed to parse sha256 from docker pull output")
}

err = storeBuildAgentSha(latest)
Expand Down
3 changes: 1 addition & 2 deletions cmd/diagnostic.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package cmd

import (
"errors"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand Down
67 changes: 60 additions & 7 deletions cmd/orb.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,15 @@ func newOrbCommand() *cobra.Command {
orbPublishCommand.PersistentFlags().StringVarP(&orbVersion, "orb-version", "o", "", "version of orb to publish")
orbPublishCommand.PersistentFlags().StringVarP(&orbID, "orb-id", "i", "", "id of orb to publish")

orbCreate := &cobra.Command{
Use: "create <namespace>/<name>",
Short: "create an orb",
RunE: createOrb,
Args: cobra.ExactArgs(1),
}

orbCreateNamespace := &cobra.Command{
Use: "create",
Use: "create <name>",
Short: "create an orb namespace",
RunE: createOrbNamespace,
Args: cobra.ExactArgs(1),
Expand All @@ -69,6 +76,7 @@ func newOrbCommand() *cobra.Command {
}

orbCommand.AddCommand(orbListCommand)
orbCommand.AddCommand(orbCreate)

orbCommand.AddCommand(orbValidateCommand)

Expand All @@ -90,20 +98,41 @@ type orb struct {
Executors map[string]struct{}
}

func addOrbElementsToBuffer(buf *bytes.Buffer, name string, elems map[string]struct{}) {
func addOrbElementsToBuffer(buf *bytes.Buffer, name string, elems map[string]struct{}) error {
var err error

if len(elems) > 0 {
buf.WriteString(fmt.Sprintf(" %s:\n", name))
_, err = buf.WriteString(fmt.Sprintf(" %s:\n", name))
if err != nil {
return err
}
for key := range elems {
buf.WriteString(fmt.Sprintf(" - %s\n", key))
_, err = buf.WriteString(fmt.Sprintf(" - %s\n", key))
if err != nil {
return err
}
}
}

return err
}

func (orb orb) String() string {
var buffer bytes.Buffer
addOrbElementsToBuffer(&buffer, "Commands", orb.Commands)
addOrbElementsToBuffer(&buffer, "Jobs", orb.Jobs)
addOrbElementsToBuffer(&buffer, "Executors", orb.Executors)

err := addOrbElementsToBuffer(&buffer, "Commands", orb.Commands)
// FIXME: refactor this to handle the error
if err != nil {
panic(err)
}
err = addOrbElementsToBuffer(&buffer, "Jobs", orb.Jobs)
if err != nil {
panic(err)
}
err = addOrbElementsToBuffer(&buffer, "Executors", orb.Executors)
if err != nil {
panic(err)
}
return buffer.String()
}

Expand Down Expand Up @@ -261,6 +290,30 @@ func publishOrb(cmd *cobra.Command, args []string) error {
return nil
}

func createOrb(cmd *cobra.Command, args []string) error {
var err error
ctx := context.Background()

arr := strings.Split(args[0], "/")

if len(arr) != 2 {
return fmt.Errorf("Invalid orb name: %s", args[0])
}

response, err := api.CreateOrb(ctx, Logger, arr[1], arr[0])

if err != nil {
return err
}

if len(response.Errors) > 0 {
return response.ToError()
}

Logger.Info("Orb created")
return nil
}

func createOrbNamespace(cmd *cobra.Command, args []string) error {
var err error
ctx := context.Background()
Expand Down
Loading

0 comments on commit 0357eb2

Please sign in to comment.