feat(controller,app): add edge apps controller

This commit is contained in:
2023-03-03 20:37:09 +01:00
parent e13de5bd0d
commit bd0d5a621a
20 changed files with 862 additions and 36 deletions

17
internal/spec/app/init.go Normal file
View File

@ -0,0 +1,17 @@
package app
import (
_ "embed"
"forge.cadoles.com/Cadoles/emissary/internal/spec"
"github.com/pkg/errors"
)
//go:embed schema.json
var schema []byte
func init() {
if err := spec.Register(NameApp, schema); err != nil {
panic(errors.WithStack(err))
}
}

View File

@ -0,0 +1,36 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://app.emissary.cadoles.com/spec.json",
"title": "AppSpec",
"description": "Emissary 'App' specification",
"type": "object",
"properties": {
"apps": {
"type": "object",
"patternProperties": {
".*": {
"type": "object",
"properties": {
"url": {
"type": "string"
},
"sha256sum": {
"type": "string"
},
"address": {
"type": "string"
},
"format": {
"type": "string",
"enum": ["zip", "tar.gz"]
}
},
"required": ["url", "sha256sum", "address", "format"],
"additionalProperties": false
}
}
}
},
"required": ["apps"],
"additionalProperties": false
}

39
internal/spec/app/spec.go Normal file
View File

@ -0,0 +1,39 @@
package app
import (
"forge.cadoles.com/Cadoles/emissary/internal/spec"
)
const NameApp spec.Name = "app.emissary.cadoles.com"
type Spec struct {
Revision int `json:"revisions"`
Apps map[string]AppEntry
}
type AppEntry struct {
URL string `json:"url"`
SHA256Sum string `json:"sha256sum"`
Address string `json:"address"`
Format string `json:"format"`
}
func (s *Spec) SpecName() spec.Name {
return NameApp
}
func (s *Spec) SpecRevision() int {
return s.Revision
}
func (s *Spec) SpecData() map[string]any {
return map[string]any{
"apps": s.Apps,
}
}
func NewSpec() *Spec {
return &Spec{}
}
var _ spec.Spec = &Spec{}

View File

@ -0,0 +1,7 @@
{
"name": "app.emissary.cadoles.com",
"data": {
"apps": {}
},
"revision": 0
}

View File

@ -0,0 +1,65 @@
package app
import (
"context"
"encoding/json"
"io/ioutil"
"testing"
"forge.cadoles.com/Cadoles/emissary/internal/spec"
"github.com/pkg/errors"
)
type validatorTestCase struct {
Name string
Source string
ShouldFail bool
}
var validatorTestCases = []validatorTestCase{
{
Name: "SpecOK",
Source: "testdata/spec-ok.json",
ShouldFail: false,
},
}
func TestValidator(t *testing.T) {
t.Parallel()
validator := spec.NewValidator()
if err := validator.Register(NameApp, schema); err != nil {
t.Fatalf("+%v", errors.WithStack(err))
}
for _, tc := range validatorTestCases {
func(tc validatorTestCase) {
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
rawSpec, err := ioutil.ReadFile(tc.Source)
if err != nil {
t.Fatalf("+%v", errors.WithStack(err))
}
var spec spec.RawSpec
if err := json.Unmarshal(rawSpec, &spec); err != nil {
t.Fatalf("+%v", errors.WithStack(err))
}
ctx := context.Background()
err = validator.Validate(ctx, &spec)
if !tc.ShouldFail && err != nil {
t.Errorf("+%v", errors.WithStack(err))
}
if tc.ShouldFail && err == nil {
t.Error("validation should have failed")
}
})
}(tc)
}
}

View File

@ -24,10 +24,10 @@ func (s *Spec) SpecRevision() int {
return s.Revision
}
func (s *Spec) SpecData() any {
return struct {
Gateways map[ID]GatewayEntry
}{Gateways: s.Gateways}
func (s *Spec) SpecData() map[string]any {
return map[string]any{
"gateways": s.Gateways,
}
}
func NewSpec() *Spec {
@ -35,3 +35,5 @@ func NewSpec() *Spec {
Gateways: make(map[ID]GatewayEntry),
}
}
var _ spec.Spec = &Spec{}

View File

@ -1,17 +1,15 @@
package spec
import "forge.cadoles.com/Cadoles/emissary/internal/agent/metadata"
type Spec interface {
SpecName() Name
SpecRevision() int
SpecData() metadata.Metadata
SpecData() map[string]any
}
type RawSpec struct {
Name Name `json:"name"`
Revision int `json:"revision"`
Data metadata.Metadata `json:"data"`
Name Name `json:"name"`
Revision int `json:"revision"`
Data map[string]any `json:"data"`
}
func (s *RawSpec) SpecName() Name {
@ -22,6 +20,8 @@ func (s *RawSpec) SpecRevision() int {
return s.Revision
}
func (s *RawSpec) SpecData() metadata.Metadata {
func (s *RawSpec) SpecData() map[string]any {
return s.Data
}
var _ Spec = &RawSpec{}

View File

@ -26,11 +26,11 @@ func (s *Spec) SpecRevision() int {
return s.Revision
}
func (s *Spec) SpecData() any {
return struct {
Config *uci.UCI `json:"config"`
PostImportCommands []*UCIPostImportCommand `json:"postImportCommands"`
}{Config: s.Config, PostImportCommands: s.PostImportCommands}
func (s *Spec) SpecData() map[string]any {
return map[string]any{
"config": s.Config,
"postImportCommands": s.PostImportCommands,
}
}
func NewSpec() *Spec {
@ -38,3 +38,5 @@ func NewSpec() *Spec {
PostImportCommands: make([]*UCIPostImportCommand, 0),
}
}
var _ spec.Spec = &Spec{}