Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC for generating API endpoints using code generation, take 2 #567

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 45 additions & 34 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ FILES ?= ./...

# List all our actual files, excluding vendor
GOPKGS ?= $(shell $(GO) list $(FILES) | grep -v /vendor/)
GOFILES ?= $(shell find . -name '*.go' | grep -v /vendor/)

# Tags specific for building
GOTAGS ?=
Expand All @@ -16,24 +15,21 @@ GOMAXPROCS ?= 4

NAME := $(notdir $(shell pwd))

# Test Service IDs
# Test Resource IDs
FASTLY_TEST_DELIVERY_SERVICE_ID ?=
DEFAULT_FASTLY_TEST_DELIVERY_SERVICE_ID = kKJb5bOFI47uHeBVluGfX1
FASTLY_TEST_COMPUTE_SERVICE_ID ?=
DEFAULT_FASTLY_TEST_COMPUTE_SERVICE_ID = XsjdElScZGjmfCcTwsYRC1
FASTLY_TEST_NGWAF_WORKSPACE_ID ?=
DEFAULT_FASTLY_TEST_NGWAF_WORKSPACE_ID = alk6DTsYKHKucJCOIavaJM
FASTLY_API_KEY ?=
#
# Enables support for tools such as https://github.com/rakyll/gotest
TEST_COMMAND ?= $(GO) test

all: mod-download dev-dependencies tidy fmt fiximports test vet staticcheck semgrep ## Runs all of the required cleaning and verification targets.
all: mod-download dev-dependencies tidy generate fmt fiximports test vet staticcheck semgrep ## Runs all of the required cleaning and verification targets.
.PHONY: all

tidy: ## Cleans the Go module.
@echo "==> Tidying module"
@$(GO) mod tidy
.PHONY: tidy

mod-download: ## Downloads the Go module.
@echo "==> Downloading Go module"
@$(GO) mod download
Expand All @@ -46,11 +42,47 @@ dev-dependencies: ## Downloads the necessary dev dependencies.
@if [[ "$$(uname)" == 'Darwin' ]]; then brew install semgrep; fi
.PHONY: dev-dependencies

tidy: ## Cleans the Go module.
@echo "==> Tidying module"
@$(GO) mod tidy
.PHONY: tidy

generate: ## Builds and runs generators, to generate code for API endpoints and tests.
@echo "==> Building generators"
@$(GO) build -o generators ./internal/generators/...
kpfleming marked this conversation as resolved.
Show resolved Hide resolved
@echo "==> Generating code from templates"
@PATH=${PATH}:$(shell pwd)/generators $(GO) generate ./...

fmt: ## Properly formats Go files and orders dependencies.
@echo "==> Running gofmt"
@gofmt -s -w fastly internal tools
.PHONY: fmt

fiximports: ## Properly formats and orders imports.
@echo "==> Fixing imports"
@goimports -w fastly internal tools
.PHONY: fiximports

test: ## Runs the test suite with VCR mocks enabled.
@echo "==> Testing ${NAME}"
@$(TEST_COMMAND) -timeout=30s -parallel=20 -tags="${GOTAGS}" ${GOPKGS} ${TESTARGS}
.PHONY: test

vet: ## Identifies common errors.
@echo "==> Running go vet"
@$(GO) vet ./...
.PHONY: vet

staticcheck: ## Runs the staticcheck linter.
@echo "==> Running staticcheck"
@staticcheck -version
@staticcheck ./...
.PHONY: staticcheck

semgrep: ## Run semgrep checker.
if command -v semgrep &> /dev/null; then semgrep ci --config auto --exclude-rule generic.secrets.security.detected-private-key.detected-private-key $(SEMGREP_ARGS); fi
.PHONY: semgrep

test-race: ## Runs the test suite with the -race flag to identify race conditions, if they exist.
@echo "==> Testing ${NAME} (race)"
@$(TEST_COMMAND) -timeout=60s -race -tags="${GOTAGS}" ${GOPKGS} ${TESTARGS}
Expand All @@ -73,6 +105,11 @@ fix-compute-fixtures: ## Updates test fixtures with a specified default Compute
@$(shell pwd)/scripts/fixFixtures.sh ${FASTLY_TEST_COMPUTE_SERVICE_ID} ${DEFAULT_FASTLY_TEST_COMPUTE_SERVICE_ID}
.PHONY: fix-compute-fixtures

fix-ngwaf-fixtures: ## Updates test fixtures with a specified default Next-Gen WAF workspace ID.
@echo "==> Updating fixtures"
@$(shell pwd)/scripts/fixFixtures.sh ${FASTLY_TEST_NGWAF_WORKSPACE_ID} ${DEFAULT_FASTLY_TEST_NGWAF_WORKSPACE_ID}
.PHONY: fix-ngwaf-fixtures

check-imports: ## A check which lists improperly-formatted imports, if they exist.
@$(shell pwd)/scripts/check-imports.sh
.PHONY: check-imports
Expand All @@ -85,35 +122,9 @@ check-mod: ## A check which lists extraneous dependencies, if they exist.
@$(shell pwd)/scripts/check-mod.sh
.PHONY: check-mod

fiximports: ## Properly formats and orders imports.
@echo "==> Fixing imports"
@goimports -w {fastly,tools}
.PHONY: fiximports

fmt: ## Properly formats Go files and orders dependencies.
@echo "==> Running gofmt"
@gofmt -s -w ${GOFILES}
.PHONY: fmt

vet: ## Identifies common errors.
@echo "==> Running go vet"
@$(GO) vet ./...
.PHONY: vet

staticcheck: ## Runs the staticcheck linter.
@echo "==> Running staticcheck"
@staticcheck -version
@staticcheck ./...
.PHONY: staticcheck

nilaway: ## Run nilaway
@nilaway ./...

# Run semgrep checker.
.PHONY: semgrep
semgrep:
if command -v semgrep &> /dev/null; then semgrep ci --config auto --exclude-rule generic.secrets.security.detected-private-key.detected-private-key $(SEMGREP_ARGS); fi

.PHONY: help
help: ## Prints this help menu.
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
Expand Down
21 changes: 14 additions & 7 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
Go Fastly uses [go-vcr](https://github.com/dnaeon/go-vcr) to "record"
and "replay" API request fixtures to improve the speed and portability
of integration tests. The test suite uses a pair of service IDs (one
for Delivery, one for Compute) for its test cases.
for Delivery, one for Compute) for its test cases. It also uses one
Next-Gen WAF workspace ID for various test cases.

Contributors without access to the test services can still update the
fixtures but with some additional steps required. Below is an example
workflow for updating a set of fixture files (where `...` should be
replaced with an appropriate value):
Contributors without access to the test services or workspace can
still update the fixtures but with some additional steps
required. Below is an example workflow for updating a set of fixture
files (where `...` should be replaced with an appropriate value):

```sh
# Remove all YAML fixture files from the specified directory.
Expand All @@ -20,18 +21,20 @@ rm -r fastly/fixtures/.../*
#
# FASTLY_TEST_DELIVERY_SERVICE_ID: should correspond to a real Delivery service you control.
# FASTLY_TEST_COMPUTE_SERVICE_ID: should correspond to a real Compute service you control.
# FASTLY_TEST_NGWAF_WORKSPACE_ID: should correspond to a real Next-Gen WAF workspace you control.
# FASTLY_API_KEY: should be a real token associated with the services you control.
# TESTARGS: allows you to use the -run flag of the 'go test' command.
#
make test FASTLY_TEST_DELIVERY_SERVICE_ID="..." FASTLY_TEST_COMPUTE_SERVICE_ID="..." FASTLY_API_KEY="..." TESTARGS="-run=..."
make test FASTLY_TEST_DELIVERY_SERVICE_ID="..." FASTLY_TEST_COMPUTE_SERVICE_ID="..." FASTLY_TEST_NGWAF_WORKSPACE_ID="..." FASTLY_API_KEY="..." TESTARGS="-run=..."
```

> **NOTE**: to run the tests with go-vcr disabled, set `VCR_DISABLE=1` (`make test-full` does this).

When adding or updating client code and integration tests,
contributors should record a new set of fixtures. Before submitting a
pull request with new or updated fixtures, we ask that contributors
update them to use the default service IDs by running two commands:
update them to use the default service IDs and workspace ID by running
three commands:

```sh
make fix-delivery-fixtures FASTLY_TEST_DELIVERY_SERVICE_ID=<your Delivery SID>
Expand All @@ -41,6 +44,10 @@ make fix-delivery-fixtures FASTLY_TEST_DELIVERY_SERVICE_ID=<your Delivery SID>
make fix-compute-fixtures FASTLY_TEST_COMPUTE_SERVICE_ID=<your Compute SID>
```

```sh
make fix-ngwaf-fixtures FASTLY_TEST_NGWAF_WORKSPACE_ID=<your Next-Gen WAF workspace ID>
```

### Important Test Tips!

There are two important things external contributors need to do when running the tests:
Expand Down
6 changes: 3 additions & 3 deletions fastly/account_event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestClient_APIEvents(t *testing.T) {

var err error
var events GetAPIEventsResponse
record(t, "events/get_events", func(c *Client) {
Record(t, "events/get_events", func(c *Client) {
events, err = c.GetAPIEvents(&GetAPIEventsFilterInput{
PageNumber: 1,
MaxResults: 1,
Expand All @@ -25,7 +25,7 @@ func TestClient_APIEvents(t *testing.T) {
}

var event *Event
record(t, "events/get_event", func(c *Client) {
Record(t, "events/get_event", func(c *Client) {
event, err = c.GetAPIEvent(&GetAPIEventInput{
EventID: events.Events[0].ID,
})
Expand All @@ -40,7 +40,7 @@ func TestClient_APIEvents(t *testing.T) {

func TestClient_GetAPIEvent_validation(t *testing.T) {
var err error
_, err = testClient.GetAPIEvent(&GetAPIEventInput{
_, err = TestClient.GetAPIEvent(&GetAPIEventInput{
EventID: "",
})
if err != ErrMissingEventID {
Expand Down
10 changes: 5 additions & 5 deletions fastly/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func (c *Client) ListACLs(i *ListACLsInput) ([]*ACL, error) {
defer resp.Body.Close()

var as []*ACL
if err := decodeBodyMap(resp.Body, &as); err != nil {
if err := DecodeBodyMap(resp.Body, &as); err != nil {
return nil, err
}
return as, nil
Expand Down Expand Up @@ -77,7 +77,7 @@ func (c *Client) CreateACL(i *CreateACLInput) (*ACL, error) {
defer resp.Body.Close()

var a *ACL
if err := decodeBodyMap(resp.Body, &a); err != nil {
if err := DecodeBodyMap(resp.Body, &a); err != nil {
return nil, err
}
return a, nil
Expand Down Expand Up @@ -114,7 +114,7 @@ func (c *Client) DeleteACL(i *DeleteACLInput) error {
defer resp.Body.Close()

var r *statusResp
if err := decodeBodyMap(resp.Body, &r); err != nil {
if err := DecodeBodyMap(resp.Body, &r); err != nil {
return err
}
if !r.Ok() {
Expand Down Expand Up @@ -154,7 +154,7 @@ func (c *Client) GetACL(i *GetACLInput) (*ACL, error) {
defer resp.Body.Close()

var a *ACL
if err := decodeBodyMap(resp.Body, &a); err != nil {
if err := DecodeBodyMap(resp.Body, &a); err != nil {
return nil, err
}
return a, nil
Expand Down Expand Up @@ -193,7 +193,7 @@ func (c *Client) UpdateACL(i *UpdateACLInput) (*ACL, error) {
defer resp.Body.Close()

var a *ACL
if err := decodeBodyMap(resp.Body, &a); err != nil {
if err := DecodeBodyMap(resp.Body, &a); err != nil {
return nil, err
}

Expand Down
20 changes: 10 additions & 10 deletions fastly/acl_entries_batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func TestClient_BatchModifyACLEntries_Create(t *testing.T) {

// When: I execute the batch create operations against the Fastly API,
var err error
record(t, fixtureBase+"create_acl_entries", func(c *Client) {
Record(t, fixtureBase+"create_acl_entries", func(c *Client) {
err = c.BatchModifyACLEntries(batchCreateOperations)
})
if err != nil {
Expand All @@ -50,7 +50,7 @@ func TestClient_BatchModifyACLEntries_Create(t *testing.T) {

// Then: I expect to be able to list all of the created ACL entries.
var actualACLEntries []*ACLEntry
record(t, fixtureBase+"list_after_create", func(c *Client) {
Record(t, fixtureBase+"list_after_create", func(c *Client) {
actualACLEntries, err = c.ListACLEntries(&ListACLEntriesInput{
ServiceID: *testService.ServiceID,
ACLID: *testACL.ACLID,
Expand Down Expand Up @@ -136,15 +136,15 @@ func TestClient_BatchModifyACLEntries_Delete(t *testing.T) {
}

var err error
record(t, fixtureBase+"create_acl_entries", func(c *Client) {
Record(t, fixtureBase+"create_acl_entries", func(c *Client) {
err = c.BatchModifyACLEntries(batchCreateOperations)
})
if err != nil {
t.Fatal(err)
}

var createdACLEntries []*ACLEntry
record(t, fixtureBase+"list_before_delete", func(client *Client) {
Record(t, fixtureBase+"list_before_delete", func(client *Client) {
createdACLEntries, err = client.ListACLEntries(&ListACLEntriesInput{
ServiceID: *testService.ServiceID,
ACLID: *testACL.ACLID,
Expand All @@ -170,7 +170,7 @@ func TestClient_BatchModifyACLEntries_Delete(t *testing.T) {
},
}

record(t, fixtureBase+"delete_acl_entries", func(c *Client) {
Record(t, fixtureBase+"delete_acl_entries", func(c *Client) {
err = c.BatchModifyACLEntries(batchDeleteOperations)
})
if err != nil {
Expand All @@ -179,7 +179,7 @@ func TestClient_BatchModifyACLEntries_Delete(t *testing.T) {

// Then: I expect to be able to list a single ACL entry.
var actualACLEntries []*ACLEntry
record(t, fixtureBase+"list_after_delete", func(client *Client) {
Record(t, fixtureBase+"list_after_delete", func(client *Client) {
actualACLEntries, err = client.ListACLEntries(&ListACLEntriesInput{
ServiceID: *testService.ServiceID,
ACLID: *testACL.ACLID,
Expand Down Expand Up @@ -235,15 +235,15 @@ func TestClient_BatchModifyACLEntries_Update(t *testing.T) {
}

var err error
record(t, fixtureBase+"create_acl_entries", func(c *Client) {
Record(t, fixtureBase+"create_acl_entries", func(c *Client) {
err = c.BatchModifyACLEntries(batchCreateOperations)
})
if err != nil {
t.Fatal(err)
}

var createdACLEntries []*ACLEntry
record(t, fixtureBase+"list_before_update", func(client *Client) {
Record(t, fixtureBase+"list_before_update", func(client *Client) {
createdACLEntries, err = client.ListACLEntries(&ListACLEntriesInput{
ServiceID: *testService.ServiceID,
ACLID: *testACL.ACLID,
Expand Down Expand Up @@ -273,7 +273,7 @@ func TestClient_BatchModifyACLEntries_Update(t *testing.T) {
},
}

record(t, fixtureBase+"update_acl_entries", func(c *Client) {
Record(t, fixtureBase+"update_acl_entries", func(c *Client) {
err = c.BatchModifyACLEntries(batchUpdateOperations)
})
if err != nil {
Expand All @@ -282,7 +282,7 @@ func TestClient_BatchModifyACLEntries_Update(t *testing.T) {

// Then: I expect to be able to list all of the ACL entries with modifications applied to a single item.
var actualACLEntries []*ACLEntry
record(t, fixtureBase+"list_after_update", func(client *Client) {
Record(t, fixtureBase+"list_after_update", func(client *Client) {
actualACLEntries, err = client.ListACLEntries(&ListACLEntriesInput{
ServiceID: *testService.ServiceID,
ACLID: *testACL.ACLID,
Expand Down
10 changes: 5 additions & 5 deletions fastly/acl_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func (c *Client) GetACLEntry(i *GetACLEntryInput) (*ACLEntry, error) {
defer resp.Body.Close()

var e *ACLEntry
if err := decodeBodyMap(resp.Body, &e); err != nil {
if err := DecodeBodyMap(resp.Body, &e); err != nil {
return nil, err
}

Expand Down Expand Up @@ -163,7 +163,7 @@ func (c *Client) CreateACLEntry(i *CreateACLEntryInput) (*ACLEntry, error) {
defer resp.Body.Close()

var e *ACLEntry
if err := decodeBodyMap(resp.Body, &e); err != nil {
if err := DecodeBodyMap(resp.Body, &e); err != nil {
return nil, err
}

Expand Down Expand Up @@ -201,7 +201,7 @@ func (c *Client) DeleteACLEntry(i *DeleteACLEntryInput) error {
defer resp.Body.Close()

var r *statusResp
if err := decodeBodyMap(resp.Body, &r); err != nil {
if err := DecodeBodyMap(resp.Body, &r); err != nil {
return err
}

Expand Down Expand Up @@ -251,7 +251,7 @@ func (c *Client) UpdateACLEntry(i *UpdateACLEntryInput) (*ACLEntry, error) {
defer resp.Body.Close()

var e *ACLEntry
if err := decodeBodyMap(resp.Body, &e); err != nil {
if err := DecodeBodyMap(resp.Body, &e); err != nil {
return nil, err
}

Expand Down Expand Up @@ -307,5 +307,5 @@ func (c *Client) BatchModifyACLEntries(i *BatchModifyACLEntriesInput) error {

var batchModifyResult map[string]string

return decodeBodyMap(resp.Body, &batchModifyResult)
return DecodeBodyMap(resp.Body, &batchModifyResult)
}
Loading
Loading