Skip to content

Commit

Permalink
SYSENG-1658: add e5e bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
Mario Schäfer committed Nov 15, 2023
1 parent dd82846 commit 9c197c8
Show file tree
Hide file tree
Showing 9 changed files with 373 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ Some examples, more below in the actual changelog (newer entries are more likely
-->

### Added
* e5e/v1: added new `Application` & `Function` resources (#317, @anx-mschaefer)

## [0.6.0] - 2023-11-10

* go-anxcloud is now tested with Go versions 1.20 and 1.21 and we might start using features only available since 1.20
Expand Down
11 changes: 11 additions & 0 deletions pkg/apis/e5e/v1/application_genclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package v1

import (
"context"
"net/url"
)

// EndpointURL returns the base URL path of the resources API
func (a *Application) EndpointURL(ctx context.Context) (*url.URL, error) {
return url.Parse("/api/e5e/v1/application.json")
}
10 changes: 10 additions & 0 deletions pkg/apis/e5e/v1/application_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package v1

// anxcloud:object

// Applications are an easy way to bring more structure to your configured functions by grouping them.
type Application struct {
omitResponseDecodeOnDestroy
Identifier string `json:"identifier,omitempty" anxcloud:"identifier"`
Name string `json:"name,omitempty"`
}
27 changes: 27 additions & 0 deletions pkg/apis/e5e/v1/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package v1

import (
"bytes"
"context"
"io"
"net/http"

"go.anx.io/go-anxcloud/pkg/api/types"
)

type omitResponseDecodeOnDestroy struct{}

func (*omitResponseDecodeOnDestroy) FilterAPIResponse(ctx context.Context, res *http.Response) (*http.Response, error) {
op, err := types.OperationFromContext(ctx)
if err != nil {
return nil, err
}

if op == types.OperationDestroy && res.StatusCode == http.StatusOK {
res.StatusCode = http.StatusNoContent
res.Body.Close()
res.Body = io.NopCloser(&bytes.Buffer{})
}

return res, nil
}
11 changes: 11 additions & 0 deletions pkg/apis/e5e/v1/function_genclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package v1

import (
"context"
"net/url"
)

// EndpointURL returns the base URL path of the resources API
func (f *Function) EndpointURL(ctx context.Context) (*url.URL, error) {
return url.Parse("/api/e5e/v1/function.json")
}
84 changes: 84 additions & 0 deletions pkg/apis/e5e/v1/function_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package v1

type StorageBackend string

const (
StorageBackendS3 = "s3"
StorageBackendGit = "git"
StorageBackendZipFile = "zip"
)

type WorkerType string

const (
WorkerTypeStandard = "standard"
)

// anxcloud:object

// Function represents the collection of all the metadata as well as the code itself
// that is needed to execute your application on the e5e platform.
type Function struct {
omitResponseDecodeOnDestroy
Identifier string `json:"identifier,omitempty" anxcloud:"identifier"`
State string `json:"state,omitempty"`
Name string `json:"name,omitempty"`
ApplicationIdentifier string `json:"application_identifier,omitempty"`
Runtime string `json:"runtime,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
StorageBackend StorageBackend `json:"storage_backend,omitempty"`
StorageBackendMeta *StorageBackendMeta `json:"storage_backend_meta,omitempty"`
EnvironmentVariables *[]EnvironmentVariable `json:"environment_variables,omitempty"`
Hostnames *[]Hostname `json:"hostnames,omitempty"`
KeepAlive int `json:"keep_alive,omitempty"`
QuotaStorage int `json:"quota_storage,omitempty"`
QuotaMemory int `json:"quota_memory,omitempty"`
QuotaCPU int `json:"quota_cpu,omitempty"`
QuotaTimeout int `json:"quota_timeout,omitempty"`
QuotaConcurrency int `json:"quota_concurrency,omitempty"`
WorkerType string `json:"worker_type,omitempty"`
}

// StorageBackendMeta is used to configure a storage backend
type StorageBackendMeta struct {
*StorageBackendMetaGit
*StorageBackendMetaS3
*StorageBackendMetaZipFile `json:"zip_file,omitempty"`
}

// StorageBackendMetaGit is used to configure a git storage backend
type StorageBackendMetaGit struct {
URL string `json:"git_url,omitempty"`
Branch string `json:"git_branch,omitempty"`
PrivateKey string `json:"git_private_key,omitempty"`
Username string `json:"git_username,omitempty"`
Password string `json:"git_password,omitempty"`
}

// StorageBackendMetaS3 is used to configure a s3 storage backend
type StorageBackendMetaS3 struct {
Endpoint string `json:"s3_endpoint,omitempty"`
BucketName string `json:"s3_bucket_name,omitempty"`
ObjectPath string `json:"s3_object_path,omitempty"`
AccessKey string `json:"s3_access_key,omitempty"`
SecretKey string `json:"s3_secret_key,omitempty"`
}

// StorageBackendMetaZipFile is used to configure a zip file storage backend
type StorageBackendMetaZipFile struct {
// Data string containing the mime-type, encoding and encoded data
// data:<mime type>;base64,<data>
Content string `json:"content"`
Name string `json:"name"`
}

type EnvironmentVariable struct {
Name string `json:"name"`
Value string `json:"value"`
Secret bool `json:"secret"`
}

type Hostname struct {
Hostname string `json:"hostname"`
IP string `json:"ip"`
}
175 changes: 175 additions & 0 deletions pkg/apis/e5e/v1/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package v1

import (
"context"
"net/http"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/ghttp"
"go.anx.io/go-anxcloud/pkg/api"
"go.anx.io/go-anxcloud/pkg/client"
)

func TestE5EAPIBindings(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "E5E API Bindings Suite")
}

var _ = Describe("mock", func() {
var (
engine api.API
srv *ghttp.Server
)

BeforeEach(func() {
var err error
srv = ghttp.NewServer()
engine, err = api.NewAPI(
api.WithClientOptions(
client.BaseURL(srv.URL()),
client.IgnoreMissingToken(),
),
)
Expect(err).ToNot(HaveOccurred())
})

AfterEach(func() {
srv.Close()
})

Context("Application", func() {
It("correctly encodes zero values", func() {
srv.AppendHandlers(ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/api/e5e/v1/application.json"),
ghttp.VerifyJSON(`{}`),
ghttp.RespondWithJSONEncoded(200, map[string]any{}),
))

err := engine.Create(context.TODO(), &Application{})
Expect(err).ToNot(HaveOccurred())
})

It("correctly encodes non-zero values", func() {
srv.AppendHandlers(ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/api/e5e/v1/application.json"),
ghttp.VerifyJSON(`{
"name": "foo"
}`),
ghttp.RespondWithJSONEncoded(200, map[string]any{}),
))

err := engine.Create(context.TODO(), &Application{
Name: "foo",
})
Expect(err).ToNot(HaveOccurred())
})

It("does not decode Destroy responses", func() {
srv.AppendHandlers(ghttp.CombineHandlers(
ghttp.VerifyRequest("DELETE", "/api/e5e/v1/application.json/fake-api-id"),
ghttp.RespondWith(http.StatusOK, "not-json"),
))

err := engine.Destroy(context.TODO(), &Application{Identifier: "fake-api-id"})
Expect(err).ToNot(HaveOccurred())
})
})

Context("Function", func() {
It("correctly encodes zero values", func() {
srv.AppendHandlers(ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/api/e5e/v1/function.json"),
ghttp.VerifyJSON(`{}`),
ghttp.RespondWithJSONEncoded(200, map[string]any{}),
))

err := engine.Create(context.TODO(), &Function{})
Expect(err).ToNot(HaveOccurred())
})

It("correctly encodes non-zero values", func() {
srv.AppendHandlers(ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/api/e5e/v1/function.json"),
ghttp.VerifyJSON(`{
"name": "foo",
"application_identifier": "bar",
"runtime": "fake-runtime",
"entrypoint": "fake-entrypoint",
"storage_backend": "fake-backend",
"storage_backend_meta": {
"git_url": "fake-url",
"git_branch": "fake-branch",
"git_private_key": "fake-private-key",
"git_username": "fake-username",
"git_password": "fake-password",
"s3_endpoint": "fake-endpoint",
"s3_bucket_name": "fake-bucket-name",
"s3_object_path": "fake-object-path",
"s3_access_key": "fake-access-key",
"s3_secret_key": "fake-secret-key",
"zip_file": {
"content": "fake-content",
"name": "fake-name"
}
},
"keep_alive": 10,
"quota_storage": 20,
"quota_memory": 30,
"quota_cpu": 40,
"quota_timeout": 50,
"quota_concurrency": 60,
"worker_type": "standard"
}`),
ghttp.RespondWithJSONEncoded(200, map[string]any{}),
))

err := engine.Create(context.TODO(), &Function{
Name: "foo",
ApplicationIdentifier: "bar",
Runtime: "fake-runtime",
Entrypoint: "fake-entrypoint",
StorageBackend: "fake-backend",
StorageBackendMeta: &StorageBackendMeta{
StorageBackendMetaS3: &StorageBackendMetaS3{
Endpoint: "fake-endpoint",
BucketName: "fake-bucket-name",
ObjectPath: "fake-object-path",
AccessKey: "fake-access-key",
SecretKey: "fake-secret-key",
},
StorageBackendMetaGit: &StorageBackendMetaGit{
URL: "fake-url",
Branch: "fake-branch",
PrivateKey: "fake-private-key",
Username: "fake-username",
Password: "fake-password",
},
StorageBackendMetaZipFile: &StorageBackendMetaZipFile{
Content: "fake-content",
Name: "fake-name",
},
},
KeepAlive: 10,
QuotaStorage: 20,
QuotaMemory: 30,
QuotaCPU: 40,
QuotaTimeout: 50,
QuotaConcurrency: 60,
WorkerType: WorkerTypeStandard,
})
Expect(err).ToNot(HaveOccurred())
})

It("does not decode Destroy responses", func() {
srv.AppendHandlers(ghttp.CombineHandlers(
ghttp.VerifyRequest("DELETE", "/api/e5e/v1/function.json/fake-api-id"),
ghttp.RespondWith(http.StatusOK, "not-json"),
))

err := engine.Destroy(context.TODO(), &Function{Identifier: "fake-api-id"})
Expect(err).ToNot(HaveOccurred())
})
})
})
17 changes: 17 additions & 0 deletions pkg/apis/e5e/v1/xxgenerated_object.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions pkg/apis/e5e/v1/xxgenerated_object_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 9c197c8

Please sign in to comment.