-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for contexts via the unstable GraphQL API (#35)
- Loading branch information
1 parent
f672452
commit 697bdd7
Showing
293 changed files
with
60,947 additions
and
36,769 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
TEST?=$$(go list ./... |grep -v 'vendor') | ||
GOFMT_FILES?=$$(find . -name '*.go' |grep -v vendor) | ||
PKG_NAME=circleci | ||
|
||
default: build | ||
|
||
build: fmtcheck | ||
go install | ||
|
||
test: fmtcheck | ||
go test -i $(TEST) || exit 1 | ||
echo $(TEST) | \ | ||
xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 | ||
|
||
testacc: fmtcheck | ||
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 30m | ||
|
||
vet: | ||
@echo "go vet ." | ||
@go vet $$(go list ./... | grep -v vendor/) ; if [ $$? -eq 1 ]; then \ | ||
echo ""; \ | ||
echo "Vet found suspicious constructs. Please check the reported constructs"; \ | ||
echo "and fix them if necessary before submitting the code for review."; \ | ||
exit 1; \ | ||
fi | ||
|
||
fmt: | ||
gofmt -s -w $(GOFMT_FILES) | ||
|
||
fmtcheck: | ||
@sh -c "'$(CURDIR)/scripts/gofmtcheck.sh'" | ||
|
||
errcheck: | ||
@sh -c "'$(CURDIR)/scripts/errcheck.sh'" | ||
|
||
test-compile: | ||
@if [ "$(TEST)" = "./..." ]; then \ | ||
echo "ERROR: Set TEST to a specific package. For example,"; \ | ||
echo " make test-compile TEST=./$(PKG_NAME)"; \ | ||
exit 1; \ | ||
fi | ||
go test -c $(TEST) $(TESTARGS) | ||
|
||
|
||
.PHONY: build test testacc vet fmt fmtcheck errcheck test-compile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package circleci | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"net/url" | ||
|
||
graphqlclient "github.com/CircleCI-Public/circleci-cli/client" | ||
restclient "github.com/jszwedko/go-circleci" | ||
) | ||
|
||
// Client provides access to the CircleCI REST and GraphQL APIs | ||
type Client struct { | ||
rest *restclient.Client | ||
graphql *graphqlclient.Client | ||
vcs string | ||
organization string | ||
} | ||
|
||
// Config configures a Client | ||
type Config struct { | ||
URL string | ||
GraphqlURL string | ||
Token string | ||
|
||
VCS string | ||
Organization string | ||
} | ||
|
||
// NewClient initializes CircleCI API clients (REST and GraphQL) and returns a new client object | ||
func NewClient(config Config) (*Client, error) { | ||
restURL, err := url.Parse(config.URL) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
graphqlURL, err := url.Parse(config.GraphqlURL) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &Client{ | ||
rest: &restclient.Client{ | ||
BaseURL: restURL, | ||
Token: config.Token, | ||
}, | ||
graphql: graphqlclient.NewClient( | ||
fmt.Sprintf("%s://%s", graphqlURL.Scheme, graphqlURL.Host), | ||
graphqlURL.Path, | ||
config.Token, | ||
false, | ||
), | ||
|
||
vcs: config.VCS, | ||
organization: config.Organization, | ||
}, nil | ||
} | ||
|
||
// Organization returns the organization for a request. If an organization is provided, | ||
// that is returned. Next, an organization configured in the provider is returned. | ||
// If neither are set, an error is returned. | ||
func (c *Client) Organization(org string) (string, error) { | ||
if org != "" { | ||
return org, nil | ||
} | ||
|
||
if c.organization != "" { | ||
return c.organization, nil | ||
} | ||
|
||
return "", errors.New("organization is required") | ||
} | ||
|
||
// GetEnvVar get the environment variable with given name | ||
// It returns an empty structure if no environment variable exists with that name | ||
func (c *Client) GetEnvVar(organization string, projectName, envVarName string) (*restclient.EnvVar, error) { | ||
org, err := c.validateOrganization(organization, projectName, envVarName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return c.rest.GetEnvVar(c.vcs, org, projectName, envVarName) | ||
} | ||
|
||
// EnvVarExists check if environment variable exists with given name | ||
func (c *Client) EnvVarExists(organization string, projectName, envVarName string) (bool, error) { | ||
org, err := c.validateOrganization(organization, projectName, envVarName) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
envVar, err := c.rest.GetEnvVar(c.vcs, org, projectName, envVarName) | ||
if err != nil { | ||
return false, err | ||
} | ||
return bool(envVar.Name != ""), nil | ||
} | ||
|
||
// AddEnvVar create an environment variable with given name and value | ||
func (c *Client) AddEnvVar(organization string, projectName, envVarName, envVarValue string) (*restclient.EnvVar, error) { | ||
org, err := c.validateOrganization(organization, projectName, envVarName) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return c.rest.AddEnvVar(c.vcs, org, projectName, envVarName, envVarValue) | ||
} | ||
|
||
// DeleteEnvVar delete the environment variable with given name | ||
func (c *Client) DeleteEnvVar(organization string, projectName, envVarName string) error { | ||
org, err := c.validateOrganization(organization, projectName, envVarName) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return c.rest.DeleteEnvVar(c.vcs, org, projectName, envVarName) | ||
} | ||
|
||
func (c *Client) validateOrganization(organization string, projectName, envVarName string) (string, error) { | ||
if organization == "" && c.organization == "" { | ||
return "", fmt.Errorf("organization has not been set for environment variable %s in project %s", projectName, envVarName) | ||
} | ||
|
||
if organization != "" { | ||
return organization, nil | ||
} | ||
|
||
return c.organization, nil | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package circleci | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/CircleCI-Public/circleci-cli/api" | ||
graphql "github.com/CircleCI-Public/circleci-cli/client" | ||
) | ||
|
||
var ( | ||
ErrContextNotFound = errors.New("context not found") | ||
) | ||
|
||
// GetContextByIDOrName lists all contexts and returns one with a matching ID or name, if found | ||
func GetContextByIDOrName(client *graphql.Client, org string, vcs string, value string) (*api.CircleCIContext, error) { | ||
ctx, err := GetContextByID(client, org, vcs, value) | ||
if err != nil && !errors.Is(err, ErrContextNotFound) { | ||
return nil, err | ||
} | ||
if ctx != nil { | ||
return ctx, nil | ||
} | ||
|
||
ctx, err = GetContextByName(client, org, vcs, value) | ||
if err != nil && !errors.Is(err, ErrContextNotFound) { | ||
return nil, err | ||
} | ||
if ctx != nil { | ||
return ctx, nil | ||
} | ||
|
||
return nil, fmt.Errorf("%w: no context with ID or name '%s' in organization '%s'", ErrContextNotFound, value, org) | ||
} | ||
|
||
// GetContextByName lists all contexts and returns one with a matching name, if found | ||
func GetContextByName(client *graphql.Client, org string, vcs string, name string) (*api.CircleCIContext, error) { | ||
res, err := api.ListContexts(client, org, vcs) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, context := range res.Organization.Contexts.Edges { | ||
if context.Node.Name == name { | ||
return &context.Node, nil | ||
} | ||
} | ||
|
||
return nil, fmt.Errorf("%w: no context with name '%s' in organization '%s'", ErrContextNotFound, name, org) | ||
} | ||
|
||
// GetContextByID lists all contexts and returns one with a matching ID, if found | ||
func GetContextByID(client *graphql.Client, org string, vcs string, ID string) (*api.CircleCIContext, error) { | ||
res, err := api.ListContexts(client, org, vcs) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, context := range res.Organization.Contexts.Edges { | ||
if context.Node.ID == ID { | ||
return &context.Node, nil | ||
} | ||
} | ||
|
||
return nil, fmt.Errorf("%w: no context with ID '%s' in organization '%s'", ErrContextNotFound, ID, org) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package circleci | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
func dataSourceCircleCIContext() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceCircleCIContextRead, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
Description: "The name of the context", | ||
}, | ||
"organization": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
Description: "The organization where the context is defined", | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceCircleCIContextRead(d *schema.ResourceData, m interface{}) error { | ||
client := m.(*Client) | ||
|
||
org, err := client.Organization(d.Get("organization").(string)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
ctx, err := GetContextByName( | ||
client.graphql, | ||
org, | ||
client.vcs, | ||
d.Get("name").(string), | ||
) | ||
if err != nil { | ||
if errors.Is(err, ErrContextNotFound) { | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
return err | ||
} | ||
|
||
d.SetId(ctx.ID) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package circleci | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
) | ||
|
||
func TestAccCircleCIContextDataSource(t *testing.T) { | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccOrgProviders, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccCircleCIContextDataSource, | ||
Check: resource.ComposeAggregateTestCheckFunc( | ||
resource.TestCheckResourceAttr("data.circleci_context.foo", "name", "terraform-test"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
const testAccCircleCIContextDataSource = ` | ||
resource "circleci_context" "foo" { | ||
name = "terraform-test" | ||
} | ||
data "circleci_context" "foo" { | ||
name = circleci_context.foo.name | ||
} | ||
` |
Oops, something went wrong.