Skip to content

Commit

Permalink
Reconfigure Default Workload Types (#240)
Browse files Browse the repository at this point in the history
* remove elf and create workload type
* add node capabilities based on build

---------

Signed-off-by: Jordan Rash <[email protected]>
  • Loading branch information
jordan-rash committed May 22, 2024
1 parent 15d1bda commit f69aefe
Show file tree
Hide file tree
Showing 27 changed files with 206 additions and 145 deletions.
6 changes: 0 additions & 6 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,6 @@ builds:
goarch:
- amd64
- arm64
- arm
goarm:
- 7
ignore:
- goos: windows
goarch: arm
ldflags:
- -s -w --X main.VERSION={{.Version}} -X main.COMMIT={{.Commit}} -X main.BUILDDATE={{.Date}} -X github.com/synadia-io/nex/internal/node.VERSION={{.Version}} -X github.com/synadia-io/nex/internal/node.COMMIT={{.Commit}} -X github.com/synadia-io/nex/internal/node.BUILDDATE={{.Date}}
- -extldflags "-static"
Expand Down
7 changes: 4 additions & 3 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/nats-io/nats.go"
"github.com/synadia-io/nex/agent/providers"
agentapi "github.com/synadia-io/nex/internal/agent-api"
"github.com/synadia-io/nex/internal/models"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
)
Expand Down Expand Up @@ -186,7 +187,7 @@ func (a *Agent) cacheExecutableArtifact(req *agentapi.DeployRequest) (*string, e
fileName := fmt.Sprintf("workload-%s", *a.md.VmID)
tempFile := path.Join(os.TempDir(), fileName)

if strings.EqualFold(runtime.GOOS, "windows") && strings.EqualFold(*req.WorkloadType, "elf") {
if strings.EqualFold(runtime.GOOS, "windows") && req.WorkloadType == models.NexWorkloadNative {
tempFile = fmt.Sprintf("%s.exe", tempFile)
}

Expand Down Expand Up @@ -289,7 +290,7 @@ func (a *Agent) handleDeploy(m *nats.Msg) {
a.provider = provider

shouldValidate := true
if !a.sandboxed && strings.EqualFold(*request.WorkloadType, agentapi.NexExecutionProviderELF) {
if !a.sandboxed && request.WorkloadType == models.NexWorkloadNative {
shouldValidate = false
}

Expand Down Expand Up @@ -469,7 +470,7 @@ func (a *Agent) submitLog(msg string, lvl agentapi.LogLevel) {
func (a *Agent) workAck(m *nats.Msg, accepted bool, msg string) error {
ack := agentapi.DeployResponse{
Accepted: accepted,
Message: agentapi.StringOrNil(msg),
Message: models.StringOrNil(msg),
}

bytes, err := json.Marshal(&ack)
Expand Down
31 changes: 9 additions & 22 deletions agent/providers/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,9 @@ import (

"github.com/synadia-io/nex/agent/providers/lib"
agentapi "github.com/synadia-io/nex/internal/agent-api"
"github.com/synadia-io/nex/internal/models"
)

// TODO: change this to "native" from "elf" when appropriate

// NexExecutionProviderNative Executable Linkable Format execution provider
const NexExecutionProviderNative = "elf"

// NexExecutionProviderV8 V8 execution provider
const NexExecutionProviderV8 = "v8"

// NexExecutionProviderOCI OCI execution provider
const NexExecutionProviderOCI = "oci"

// NexExecutionProviderWasm Wasm execution provider
const NexExecutionProviderWasm = "wasm"

// ExecutionProvider implementations provide support for a specific
// execution environment pattern -- e.g., statically-linked ELF
// binaries, serverless JavaScript functions, OCI images, Wasm, etc.
Expand All @@ -42,19 +29,19 @@ type ExecutionProvider interface {

// NewExecutionProvider initializes and returns an execution provider for a given work request
func NewExecutionProvider(params *agentapi.ExecutionProviderParams) (ExecutionProvider, error) {
if params.WorkloadType == nil {
return nil, errors.New("execution provider factory requires a workload type parameter")
}
// if params.WorkloadType == nil {
// return nil, errors.New("execution provider factory requires a workload type parameter")
// }

switch *params.WorkloadType {
case NexExecutionProviderNative:
switch params.WorkloadType {
case models.NexWorkloadNative:
return lib.InitNexExecutionProviderNative(params)
case NexExecutionProviderV8:
case models.NexWorkloadV8:
return lib.InitNexExecutionProviderV8(params)
case NexExecutionProviderOCI:
case models.NexWorkloadOCI:
// TODO-- return lib.InitNexExecutionProviderOCI(params), nil
return nil, errors.New("oci execution provider not yet implemented")
case NexExecutionProviderWasm:
case models.NexWorkloadWasm:
return lib.InitNexExecutionProviderWasm(params)
default:
break
Expand Down
2 changes: 1 addition & 1 deletion agent/providers/lib/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func validateNativeBinary(path string) error {
func verifyStatic(elf *elf.File) error {
for _, prog := range elf.Progs {
if prog.ProgHeader.Type == 3 { // PT_INTERP
return errors.New("elf binary contains at least one dynamically linked dependency")
return errors.New("native binary contains at least one dynamically linked dependency")
}
}
return nil
Expand Down
19 changes: 10 additions & 9 deletions control-api/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import (

"github.com/nats-io/jwt/v2"
"github.com/nats-io/nkeys"
"github.com/synadia-io/nex/internal/models"
)

type DeployRequest struct {
Argv []string `json:"argv,omitempty"`
Description *string `json:"description,omitempty"`
WorkloadType *string `json:"type"`
Location *url.URL `json:"location"`
Essential *bool `json:"essential,omitempty"`
Argv []string `json:"argv,omitempty"`
Description *string `json:"description,omitempty"`
WorkloadType models.NexWorkload `json:"type"`
Location *url.URL `json:"location"`
Essential *bool `json:"essential,omitempty"`

// Contains claims for the workload: name, hash
WorkloadJwt *string `json:"workload_jwt"`
Expand Down Expand Up @@ -69,7 +70,7 @@ func NewDeployRequest(opts ...RequestOption) (*DeployRequest, error) {
req := &DeployRequest{
Argv: reqOpts.argv,
Description: &reqOpts.workloadDescription,
WorkloadType: &reqOpts.workloadType,
WorkloadType: reqOpts.workloadType,
Location: &reqOpts.location,
WorkloadJwt: &workloadJwt,
Environment: &encryptedEnv,
Expand Down Expand Up @@ -145,7 +146,7 @@ func (request *DeployRequest) DecryptRequestEnvironment(recipientXKey nkeys.KeyP
type requestOptions struct {
argv []string
workloadName string
workloadType string
workloadType models.NexWorkload
workloadDescription string
location url.URL
env map[string]string
Expand Down Expand Up @@ -177,8 +178,8 @@ func WorkloadName(name string) RequestOption {
}
}

// Type of the workload, e.g., one of "elf", "v8", "oci", "wasm" for this request
func WorkloadType(workloadType string) RequestOption {
// Type of the workload, e.g., one of "native", "v8", "oci", "wasm" for this request
func WorkloadType(workloadType models.NexWorkload) RequestOption {
return func(o requestOptions) requestOptions {
o.workloadType = workloadType
return o
Expand Down
33 changes: 17 additions & 16 deletions control-api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"log/slog"

cloudevents "github.com/cloudevents/sdk-go"
"github.com/synadia-io/nex/internal/models"
)

const (
Expand Down Expand Up @@ -52,10 +53,10 @@ type WorkloadPingResponse struct {
}

type WorkloadPingMachineSummary struct {
Id string `json:"id"`
Namespace string `json:"namespace"`
Name string `json:"name"`
WorkloadType string `json:"type"`
Id string `json:"id"`
Namespace string `json:"namespace"`
Name string `json:"name"`
WorkloadType models.NexWorkload `json:"type"`
}

type LameDuckResponse struct {
Expand All @@ -70,13 +71,13 @@ type MemoryStat struct {
}

type InfoResponse struct {
Version string `json:"version"`
Uptime string `json:"uptime"`
PublicXKey string `json:"public_xkey"`
Tags map[string]string `json:"tags,omitempty"`
Memory *MemoryStat `json:"memory,omitempty"`
Machines []MachineSummary `json:"machines"`
SupportedWorkloadTypes []string `json:"supported_workload_types,omitempty"`
Version string `json:"version"`
Uptime string `json:"uptime"`
PublicXKey string `json:"public_xkey"`
Tags map[string]string `json:"tags,omitempty"`
Memory *MemoryStat `json:"memory,omitempty"`
Machines []MachineSummary `json:"machines"`
SupportedWorkloadTypes []models.NexWorkload `json:"supported_workload_types,omitempty"`
}

type MachineSummary struct {
Expand All @@ -88,11 +89,11 @@ type MachineSummary struct {
}

type WorkloadSummary struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Runtime string `json:"runtime"`
WorkloadType string `json:"type"`
Hash string `json:"hash"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Runtime string `json:"runtime"`
WorkloadType models.NexWorkload `json:"type"`
Hash string `json:"hash"`
}

type Envelope struct {
Expand Down
54 changes: 21 additions & 33 deletions internal/agent-api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,13 @@ import (
"errors"
"io"
"net/url"
"strings"
"time"

"github.com/nats-io/jwt/v2"
"github.com/nats-io/nats.go"
"github.com/synadia-io/nex/internal/models"
)

// Executable Linkable Format execution provider
const NexExecutionProviderELF = "elf"

// V8 execution provider
const NexExecutionProviderV8 = "v8"

// OCI execution provider
const NexExecutionProviderOCI = "oci"

// Wasm execution provider
const NexExecutionProviderWasm = "wasm"

// Name of the internal, non-public bucket for sharing files between host and agent
const WorkloadCacheBucket = "NEXCACHE"

Expand Down Expand Up @@ -56,19 +44,19 @@ type ExecutionProviderParams struct {

// DeployRequest processed by the agent
type DeployRequest struct {
Argv []string `json:"argv,omitempty"`
DecodedClaims jwt.GenericClaims `json:"-"`
Description *string `json:"description"`
Environment map[string]string `json:"environment"`
Essential *bool `json:"essential,omitempty"`
Hash string `json:"hash,omitempty"`
Namespace *string `json:"namespace,omitempty"`
RetriedAt *time.Time `json:"retried_at,omitempty"`
RetryCount *uint `json:"retry_count,omitempty"`
TotalBytes int64 `json:"total_bytes,omitempty"`
TriggerSubjects []string `json:"trigger_subjects"`
WorkloadName *string `json:"workload_name,omitempty"`
WorkloadType *string `json:"workload_type,omitempty"`
Argv []string `json:"argv,omitempty"`
DecodedClaims jwt.GenericClaims `json:"-"`
Description *string `json:"description"`
Environment map[string]string `json:"environment"`
Essential *bool `json:"essential,omitempty"`
Hash string `json:"hash,omitempty"`
Namespace *string `json:"namespace,omitempty"`
RetriedAt *time.Time `json:"retried_at,omitempty"`
RetryCount *uint `json:"retry_count,omitempty"`
TotalBytes int64 `json:"total_bytes,omitempty"`
TriggerSubjects []string `json:"trigger_subjects"`
WorkloadName *string `json:"workload_name,omitempty"`
WorkloadType models.NexWorkload `json:"workload_type,omitempty"`

Stderr io.Writer `json:"-"`
Stdout io.Writer `json:"-"`
Expand All @@ -90,14 +78,14 @@ func (request *DeployRequest) IsEssential() bool {

// Returns true if the run request supports essential flag
func (request *DeployRequest) SupportsEssential() bool {
return strings.EqualFold(*request.WorkloadType, "elf") ||
strings.EqualFold(*request.WorkloadType, "oci")
return request.WorkloadType == models.NexWorkloadNative ||
request.WorkloadType == models.NexWorkloadOCI
}

// Returns true if the run request supports trigger subjects
func (request *DeployRequest) SupportsTriggerSubjects() bool {
return (strings.EqualFold(*request.WorkloadType, "v8") ||
strings.EqualFold(*request.WorkloadType, "wasm")) &&
return (request.WorkloadType == models.NexWorkloadV8 ||
request.WorkloadType == models.NexWorkloadWasm) &&
len(request.TriggerSubjects) > 0
}

Expand All @@ -124,10 +112,10 @@ func (r *DeployRequest) Validate() error {
err = errors.Join(err, errors.New("total bytes is required"))
}

if r.WorkloadType == nil {
if r.WorkloadType == "" {
err = errors.Join(err, errors.New("workload type is required"))
} else if (strings.EqualFold(*r.WorkloadType, NexExecutionProviderV8) ||
strings.EqualFold(*r.WorkloadType, NexExecutionProviderWasm)) &&
} else if (r.WorkloadType == models.NexWorkloadV8 ||
r.WorkloadType == models.NexWorkloadWasm) &&
len(r.TriggerSubjects) == 0 {
err = errors.Join(err, errors.New("at least one trigger subject is required for this workload type"))
}
Expand Down
2 changes: 1 addition & 1 deletion internal/models/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type RunOptions struct {
TargetNode string
WorkloadUrl *url.URL
Name string
WorkloadType string
WorkloadType NexWorkload
Description string
PublisherXkeyFile string
ClaimsIssuerFile string
Expand Down
14 changes: 6 additions & 8 deletions internal/models/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/nats-io/nats-server/v2/server"
"github.com/splode/fname"
agentapi "github.com/synadia-io/nex/internal/agent-api"
)

const (
Expand All @@ -25,8 +24,7 @@ const (
)

var (
// docker/OCI needs to be explicitly enabled in node configuration
DefaultWorkloadTypes = []string{"elf", "v8", "wasm"}
DefaultWorkloadTypes = []NexWorkload{NexWorkloadNative}

DefaultBinPath = append([]string{"/usr/local/bin"}, filepath.SplitList(os.Getenv("PATH"))...)

Expand Down Expand Up @@ -59,7 +57,7 @@ type NodeConfiguration struct {
RootFsFilepath string `json:"rootfs_filepath"`
Tags map[string]string `json:"tags,omitempty"`
ValidIssuers []string `json:"valid_issuers,omitempty"`
WorkloadTypes []string `json:"workload_types,omitempty"`
WorkloadTypes []NexWorkload `json:"workload_types,omitempty"`
HostServicesConfiguration *HostServicesConfig `json:"host_services,omitempty"`

// Public NATS server options; when non-nil, a public "userland" NATS server is started during node init
Expand Down Expand Up @@ -132,7 +130,7 @@ func DefaultNodeConfiguration() NodeConfiguration {
BinPath: DefaultBinPath,
// CAUTION: This needs to be the IP of the node server's internal NATS --as visible to the agent.
// This is not necessarily the address on which the internal NATS server is actually listening inside the node.
InternalNodeHost: agentapi.StringOrNil(DefaultInternalNodeHost),
InternalNodeHost: StringOrNil(DefaultInternalNodeHost),
InternalNodePort: &defaultNodePort,
MachinePoolSize: 1,
MachineTemplate: MachineTemplate{
Expand Down Expand Up @@ -171,9 +169,9 @@ func DefaultNodeConfiguration() NodeConfiguration {
if !config.NoSandbox {
config.CNI = CNIDefinition{
BinPath: DefaultCNIBinPath,
NetworkName: agentapi.StringOrNil(DefaultCNINetworkName),
InterfaceName: agentapi.StringOrNil(DefaultCNIInterfaceName),
Subnet: agentapi.StringOrNil(DefaultCNISubnet),
NetworkName: StringOrNil(DefaultCNINetworkName),
InterfaceName: StringOrNil(DefaultCNIInterfaceName),
Subnet: StringOrNil(DefaultCNISubnet),
}
}

Expand Down
16 changes: 16 additions & 0 deletions internal/models/node_capabilities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package models

type NexWorkload string

const (
NexWorkloadNative NexWorkload = "native"
NexWorkloadV8 NexWorkload = "v8"
NexWorkloadOCI NexWorkload = "oci"
NexWorkloadWasm NexWorkload = "wasm"
)

type NodeCapabilities struct {
Sandboxable bool `json:"sandboxable"`
SupportedProviders []NexWorkload `json:"supported_providers"`
NodeTags map[string]string `json:"node_tags"`
}
Loading

0 comments on commit f69aefe

Please sign in to comment.