Skip to content

Commit

Permalink
Add docstrings for all new public things
Browse files Browse the repository at this point in the history
In the process of this I also made some public things private, as I
realized that they weren't being used externally.

I also realized while writing docstrings that one helper function was no
longer necessary - very small refactor. Plus fixed a typo in a test type
name (GraphQLRequst).
  • Loading branch information
johnswanson committed Aug 12, 2020
1 parent c4a8029 commit 308499e
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 58 deletions.
7 changes: 6 additions & 1 deletion api/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import (
"time"
)

// An EnvironmentVariable has a Variable, a ContextID (its owner), and a
// CreatedAt date.
type EnvironmentVariable struct {
Variable string
ContextID string
CreatedAt string // TODO: make this a time.Time
CreatedAt time.Time
}

// A Context is the owner of EnvironmentVariables.
type Context struct{
CreatedAt time.Time `json:"created_at"`
ID string `json:"id"`
Name string `json:"name"`
}

// ContextInterface is the interface to interact with contexts and environment
// variables.
type ContextInterface interface {
Contexts(vcs, org string) (*[]Context, error)
ContextByName(vcs, org, name string) (*Context, error)
Expand Down
33 changes: 21 additions & 12 deletions api/context_graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,20 @@ type GraphQLContextClient struct {
Client *graphql.Client
}

type Resource struct {
Variable string
CreatedAt string
TruncatedValue string
}

type CircleCIContext struct {
type circleCIContext struct {
ID string
Name string
CreatedAt string
Groups struct {
}
}

type ContextsQueryResponse struct {
type contextsQueryResponse struct {
Organization struct {
Id string
Contexts struct {
Edges []struct {
Node CircleCIContext
Node circleCIContext
}
}
}
Expand All @@ -52,6 +46,7 @@ func improveVcsTypeError(err error) error {
return err
}

// CreateContext creates a new Context in the supplied organization.
func (c *GraphQLContextClient) CreateContext(vcsType, orgName, contextName string) (error) {
cl := c.Client

Expand Down Expand Up @@ -109,6 +104,8 @@ func (c *GraphQLContextClient) CreateContext(vcsType, orgName, contextName strin
return nil
}

// ContextByName returns the Context in the given organization with the given
// name.
func (c *GraphQLContextClient) ContextByName(vcs, org, name string) (*Context, error) {
contexts , err := c.Contexts(vcs, org)
if err != nil {
Expand All @@ -122,6 +119,8 @@ func (c *GraphQLContextClient) ContextByName(vcs, org, name string) (*Context, e
return nil, errors.New("No context found with that name")
}

// EnvironmentVariables returns all of the environment variables in this
// context.
func (c *GraphQLContextClient) EnvironmentVariables(contextID string) (*[]EnvironmentVariable, error) {
cl := c.Client
query := `
Expand Down Expand Up @@ -152,6 +151,7 @@ func (c *GraphQLContextClient) EnvironmentVariables(contextID string) (*[]Enviro
return &resp.Context.Resources, nil
}

// Contexts returns all of the Contexts owned by this organization.
func (c *GraphQLContextClient) Contexts(vcsType, orgName string) (*[]Context, error) {
cl := c.Client
// In theory we can lookup the organization by name and its contexts in
Expand Down Expand Up @@ -210,7 +210,7 @@ func (c *GraphQLContextClient) Contexts(vcsType, orgName string) (*[]Context, er

request.Var("orgId", org.Organization.ID)

var response ContextsQueryResponse
var response contextsQueryResponse
err = cl.Run(request, &response)
if err != nil {
return nil, errors.Wrapf(improveVcsTypeError(err), "failed to load context list")
Expand All @@ -232,6 +232,9 @@ func (c *GraphQLContextClient) Contexts(vcsType, orgName string) (*[]Context, er
return &contexts, nil
}

// DeleteEnvironmentVariable deletes the environment variable from the context.
// It returns an error if one occurred. It does not return an error if the
// environment variable did not exist.
func (c *GraphQLContextClient) DeleteEnvironmentVariable(contextId, variableName string) error {
cl := c.Client
query := `
Expand Down Expand Up @@ -266,14 +269,17 @@ func (c *GraphQLContextClient) DeleteEnvironmentVariable(contextId, variableName

var response struct {
RemoveEnvironmentVariable struct {
Context CircleCIContext
Context circleCIContext
}
}

err := cl.Run(request, &response)
return errors.Wrap(improveVcsTypeError(err), "failed to delete environment varaible")
}

// CreateEnvironmentVariable creates a new environment variable in the given
// context. Note that the GraphQL API does not support upsert, so an error will
// be returned if the env var already exists.
func (c *GraphQLContextClient) CreateEnvironmentVariable(contextId, variableName, secretValue string) error {
cl := c.Client
query := `
Expand Down Expand Up @@ -318,7 +324,7 @@ func (c *GraphQLContextClient) CreateEnvironmentVariable(contextId, variableName

var response struct {
StoreEnvironmentVariable struct {
Context CircleCIContext
Context circleCIContext
Error struct {
Type string
}
Expand All @@ -336,6 +342,7 @@ func (c *GraphQLContextClient) CreateEnvironmentVariable(contextId, variableName
return nil
}

// DeleteContext will delete the context with the given ID.
func (c *GraphQLContextClient) DeleteContext(contextId string) error {
cl := c.Client
query := `
Expand Down Expand Up @@ -363,6 +370,8 @@ func (c *GraphQLContextClient) DeleteContext(contextId string) error {
return errors.Wrap(improveVcsTypeError(err), "failed to delete context")
}

// NewContextGraphqlClient returns a new client satisfying the
// api.ContextInterface interface via the GraphQL API.
func NewContextGraphqlClient(host, endpoint, token string, debug bool) *GraphQLContextClient {
return &GraphQLContextClient{
Client: graphql.NewClient(host, endpoint, token, debug),
Expand Down
78 changes: 43 additions & 35 deletions api/context_rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"github.com/pkg/errors"
)

// ContextRestClient communicates with the CircleCI REST API to ask questions
// about contexts. It satisfies api.ContextInterface.
type ContextRestClient struct {
token string
server string
Expand All @@ -32,7 +34,7 @@ type listContextsResponse struct {
params *listContextsParams
}

type ErrorResponse struct {
type errorResponse struct {
Message *string `json:"message"`
}

Expand All @@ -53,6 +55,8 @@ func toSlug(vcs, org string) *string {
return &slug
}

// DeleteEnvironmentVariable deletes the environment variable in the context. It
// does not return an error if the environment variable did not exist.
func (c *ContextRestClient) DeleteEnvironmentVariable(contextID, variable string) error {
req, err := c.newDeleteEnvironmentVariableRequest(contextID, variable)
if err != nil {
Expand All @@ -71,7 +75,7 @@ func (c *ContextRestClient) DeleteEnvironmentVariable(contextID, variable string
}

if resp.StatusCode != 200 {
var dest ErrorResponse
var dest errorResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return err
}
Expand All @@ -80,6 +84,7 @@ func (c *ContextRestClient) DeleteEnvironmentVariable(contextID, variable string
return nil
}

// CreateContext creates a new context in the supplied organization.
func (c *ContextRestClient) CreateContext(vcs, org, name string) (error) {
req, err := c.newCreateContextRequest(vcs, org, name)
if err != nil {
Expand All @@ -98,7 +103,7 @@ func (c *ContextRestClient) CreateContext(vcs, org, name string) (error) {
return err
}
if resp.StatusCode != 200 {
var dest ErrorResponse
var dest errorResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return err
}
Expand All @@ -111,6 +116,7 @@ func (c *ContextRestClient) CreateContext(vcs, org, name string) (error) {
return nil
}

// CreateEnvironmentVariable creates OR UPDATES an environment variable.
func (c *ContextRestClient) CreateEnvironmentVariable(contextID, variable, value string) error {
req, err := c.newCreateEnvironmentVariableRequest(contextID, variable, value)
if err != nil {
Expand All @@ -128,7 +134,7 @@ func (c *ContextRestClient) CreateEnvironmentVariable(contextID, variable, value
return err
}
if resp.StatusCode != 200 {
var dest ErrorResponse
var dest errorResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return err
}
Expand All @@ -137,6 +143,7 @@ func (c *ContextRestClient) CreateEnvironmentVariable(contextID, variable, value
return nil
}

// DeleteContext deletes the context with the given ID.
func (c *ContextRestClient) DeleteContext(contextID string) error {
req, err := c.newDeleteContextRequest(contextID)

Expand All @@ -155,7 +162,7 @@ func (c *ContextRestClient) DeleteContext(contextID string) error {
return err
}
if resp.StatusCode != 200 {
var dest ErrorResponse
var dest errorResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return err
}
Expand All @@ -164,6 +171,9 @@ func (c *ContextRestClient) DeleteContext(contextID string) error {
return nil
}

// EnvironmentVariables returns all of the environment variables owned by the
// given context. Note that pagination is not currently supported - we get all
// pages of env vars and return them all.
func (c *ContextRestClient) EnvironmentVariables(contextID string) (*[]EnvironmentVariable, error) {
envVars, error := c.listAllEnvironmentVariables(
&listEnvironmentVariablesParams{
Expand All @@ -173,6 +183,9 @@ func (c *ContextRestClient) EnvironmentVariables(contextID string) (*[]Environme
return &envVars, error
}

// Contexts returns all of the contexts owned by the given org. Note that
// pagination is not currently supported - we get all pages of contexts and
// return them all.
func (c *ContextRestClient) Contexts(vcs, org string) (*[]Context, error) {
contexts, error := c.listAllContexts(
&listContextsParams{
Expand All @@ -182,13 +195,26 @@ func (c *ContextRestClient) Contexts(vcs, org string) (*[]Context, error) {
return &contexts, error
}

// ContextByName finds a single context by its name and returns it.
func (c *ContextRestClient) ContextByName(vcs, org, name string) (*Context, error) {
return c.getContextByName(
&listContextsParams{
OwnerSlug: toSlug(vcs, org),
},
name,
)
params := &listContextsParams{
OwnerSlug: toSlug(vcs, org),
}
for {
resp, err := c.listContexts(params)
if err != nil {
return nil, err
}
for _, context := range resp.Items {
if context.Name == name {
return &context, nil
}
}
if resp.NextPageToken == nil {
return nil, fmt.Errorf("Cannot find context named '%s'", name)
}
params.PageToken = resp.NextPageToken
}
}

func (c *ContextRestClient) listAllEnvironmentVariables (params *listEnvironmentVariablesParams) (envVars []EnvironmentVariable, err error) {
Expand Down Expand Up @@ -229,28 +255,6 @@ func (c *ContextRestClient) listAllContexts(params *listContextsParams) (context
return contexts, nil
}

func (c *ContextRestClient) getContextByName(params *listContextsParams, name string) (*Context, error) {
resp, err := c.listContexts(params)
if err != nil {
return nil, err
}

for _, context := range resp.Items {
if context.Name == name {
return &context, nil
}
}
if resp.NextPageToken != nil {
params.PageToken = resp.NextPageToken
context, err := c.getContextByName(params, name)
if err != nil {
return nil, err
}
return context, nil
}
return nil, fmt.Errorf("Cannot find context named '%s'", name)
}

func (c *ContextRestClient) listEnvironmentVariables (params *listEnvironmentVariablesParams) (*listEnvironmentVariablesResponse, error) {
req, err := c.newListEnvironmentVariablesRequest(params)
if err != nil {
Expand All @@ -268,7 +272,7 @@ func (c *ContextRestClient) listEnvironmentVariables (params *listEnvironmentVar
return nil, err
}
if resp.StatusCode != 200 {
var dest ErrorResponse
var dest errorResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err
}
Expand Down Expand Up @@ -302,7 +306,7 @@ func (c *ContextRestClient) listContexts (params *listContextsParams) (*listCont
return nil, err
}
if resp.StatusCode != 200 {
var dest ErrorResponse
var dest errorResponse
if err := json.Unmarshal(bodyBytes, &dest); err != nil {
return nil, err

Expand Down Expand Up @@ -472,6 +476,8 @@ func (c *ContextRestClient) newHTTPRequest(method, url string, body io.Reader) (
return req, nil
}

// EnsureExists verifies that the REST API exists and has the necessary
// endpoints to interact with contexts and env vars.
func (c *ContextRestClient) EnsureExists() error {
queryURL, err := url.Parse(c.server)
if err != nil {
Expand Down Expand Up @@ -515,6 +521,8 @@ func (c *ContextRestClient) EnsureExists() error {
return nil
}

// NewContextRestClient returns a new client satisfying the api.ContextInterface
// interface via the REST API.
func NewContextRestClient(host, endpoint, token string) (*ContextRestClient, error) {
// Ensure server ends with a slash
if !strings.HasSuffix(endpoint, "/") {
Expand Down
Loading

0 comments on commit 308499e

Please sign in to comment.