synpse

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 12, 2021 License: Apache-2.0 Imports: 20 Imported by: 0

README


The easiest way to bootstrap your devices and deploy applications.
Synpse manages OTA deployment & updates, provides SSH and network access.


WebsiteDiscussionsDocsDiscordCloud

Synpse v1 API client

Build Status Doc

Synpse provides your device fleet management, application deployment and their configuration. Whole process is simple with very low learning curve.

  • 🚧 This API client is still under active development, the methods can be changed 🚧 *

Prerequisites

Install

go get github.com/synpse-hq/synpse-go

Authentication

To authenticate, we recommend using a project level access key that you can generate here: https://cloud.synpse.net/service-accounts.

Alternatively, use Personal Access Keys, however, they will be able to manage multiple projects.

Examples

Let's start with creating an client API:

package main

import (
  "os"
  "fmt"

  "github.com/synpse-hq/synpse-go"
)

func main() {
  // Create a new API client with a specified access key. You can get your access key
  // from https://cloud.synpse.net/service-accounts
  apiClient, _ := synpse.NewWithProject(os.Getenv("SYNPSE_PROJECT_ACCESS_KEY"), os.Getenv("SYNPSE_PROJECT_ID"))    
}

Registering New Device

When automating your device fleet operations, you will most likely need to create and manage device registration tokens. These tokens can be created with a set of labels and environment variables which will then be inherited by any device that registers using it.

  // In this example we use user ID but it could be anything else like company name, location identifier, etc.
  var userID = "usr_mkalpxzlab"
  // Optional max registrations. It's a good practice to set these to sane limits. If you expect only one device
  // to register with this token, set it to 1.
  var maxRegistrations = 10

  // Create a registration token
  drt, _ := apiClient.CreateRegistrationToken(ctx, synpse.DeviceRegistrationToken{
    Name:                 "drt-" + userID,
    MaxRegistrations:     &maxRegistrations,                 // optional 
    Labels:               map[string]string{"user": userID}, // optional
  })

  // Use this token together with your project ID:
  // 
  // curl https://downloads.synpse.net/install.sh | \
  //   AGENT_PROJECT={{ PROJECT_ID }} \
  //   AGENT_REGISTRATION_TOKEN={{ DEVICE_REGISTRATION_TOKEN }} \
  //   bash


  // Once registration token is created, you can use device filtering to find it:
  devicesResp, _ := apiClient.ListDevices(context.Background(), &synpse.ListDevicesRequest{
    Labels: map[string]string{
      "user": userID, 
    },
  })

List Devices

  // List devices
  devicesResp, _ := apiClient.ListDevices(context.Background(), &synpse.ListDevicesRequest{})

  // Print device names
  for _, device := range devicesResp.Devices {
    fmt.Println(device.Name)
  }

Here we list an already registered devices. Default page size is 100, if you have more devices, use pagination options and iterate for as long as you have the next page token.

Filtering devices during the query is almost always the preferred solution. You can filter devices by labels:

  // List devices that have this label
  devicesResp, _ := apiClient.ListDevices(context.Background(), &synpse.ListDevicesRequest{
    Labels: map[string]string{
      "group": "one", 
    },
  })

Create Application

Applications in Synpse can either:

  • Run on all devices in the project
  • Run on devices with matching labels

To create an application that will run on all devices:

  // Create an application in 'default' namespace that will be deployed on all devices
  application, err := apiClient.CreateApplication(context.Background(), "default", synpse.Application{
    Name:        "app-name",
    Scheduling: synpse.Scheduling{
      Type: synpse.ScheduleTypeAllDevices,
    },
    Spec: synpse.ApplicationSpec{
      ContainerSpec: []synpse.ContainerSpec{
        {
          Name:  "hello",
          Image: "quay.io/synpse/hello-synpse-go:latest",
          Ports: []string{"8080:8080"},
        },
      },
    },
  })

or only on specific devices, based on label selector:

  // Create an application that will be deployed on devices that have our specified label
  application, err := apiClient.CreateApplication(context.Background(), "default", synpse.Application{
    Name:        "app-name",
    Scheduling: synpse.Scheduling{
      Type: synpse.ScheduleTypeConditional,
      Selector: {
        "location": "power-plant",
      }
    },
    Spec: synpse.ApplicationSpec{
      ContainerSpec: []synpse.ContainerSpec{
        {
          Name:  "hello",
          Image: "quay.io/synpse/hello-synpse-go:latest",
          Ports: []string{"8080:8080"},
        },
      },
    },
  })

Update Application

During the normal lifecycle, you will be updating application many times. For example if you want to update the Docker image or expose additional ports, use the UpdateApplication method:

  // Create an application that will be deployed on devices that have our specified label
  application, err := apiClient.UpdateApplication(context.Background(), "default", synpse.Application{
    ID:          app.ID,
    Name:        "app-name",
    Scheduling: synpse.Scheduling{
      Type: synpse.ScheduleTypeConditional,
      Selector: {
        "location": "power-plant",
      }
    },
    Spec: synpse.ApplicationSpec{
      ContainerSpec: []synpse.ContainerSpec{
        {
          Name:  "hello",
          Image: "quay.io/synpse/hello-synpse-go:new",
          Ports: []string{
            "8080:8080",
            "8888:8888",            
          },
        },
      },
    },
  })

List Applications

To list applications:

    applications, err := apiClient.ListApplications(
      context.Background(), 
      &synpse.ListApplicationsRequest{Namespace: "default"},
    )
    for _, app := range applications {
      fmt.Println(app.Name)
    }

Delete Applications:

You can remove applications by using name or ID:

  err := apiClient.DeleteApplication(context.Background(), "default", "app-name")

Documentation

Overview

Package synpse implements the Synpse v1 API.

Index

Constants

View Source
const (
	ScheduleTypeNoDevices   = "NoDevices" // Optional, defaults when no type and no selectors are specified
	ScheduleTypeAllDevices  = "AllDevices"
	ScheduleTypeConditional = "Conditional" // Optional, defaults when no type but selectors are specified
)
View Source
const (
	NetworkModeHost     = "host"
	NetworkModeIsolated = "isolated"
	NetworkModeBridge   = "bridge"
)
View Source
const (
	DeviceStatusOnline  = DeviceStatus("online")
	DeviceStatusOffline = DeviceStatus("offline")
)
View Source
const (
	DefaultPageSize = 100
	MaxPageSize     = 500
)
View Source
const (
	EffectAllow = Effect("allow")
	EffectDeny  = Effect("deny")
)
View Source
const (
	// APIURL is the public cloud API endpoint.
	APIURL = "https://cloud.synpse.net/api"
	// UserAgent is the default user agent set on the requests
	UserAgent = "synpse-go/v1"
	// ClientClientRequestID is the header key for the client request ID
	ClientClientRequestID = "synpse-client-request-id"
)
View Source
const (
	// AuthToken specifies that we should authenticate with an API key & secret
	AuthToken = 1 << iota
)

Variables

View Source
var (
	HeaderNextPageToken     = "Next-Page-Token"
	HeaderPreviousPageToken = "Previous-Page-Token"
	HeaderPageSize          = "Page-Size"
	HeaderTotalItems        = "Total-Items"
)

Pagination headers

View Source
var (
	PaginationQueryPageToken = "pageToken"
	PaginationPageSize       = "pageSize"
)

Common pagination query args

View Source
var (
	ErrEmptyCredentials      = errors.New("invalid credentials: access key must not be empty")
	ErrNamespaceNotSpecified = errors.New("namespace not specified")
)

Errors

Functions

This section is empty.

Types

type API

type API struct {
	APIAccessKey string
	BaseURL      string
	UserAgent    string
	ProjectID    string
	// contains filtered or unexported fields
}

API holds the configuration for the current API client. A client should not be modified concurrently.

func New

func New(accessKey string, opts ...Option) (*API, error)

New creates a new Synpse v1 API client.

func NewWithProject

func NewWithProject(accessKey, projectID string, opts ...Option) (*API, error)

NewWithProject creates a new Synpse v1 API client with a preconfigured project.

func (*API) CreateApplication

func (api *API) CreateApplication(ctx context.Context, namespace string, application Application) (*Application, error)

CreateApplication creates a new application in the specified namespace. Applications API ref: https://docs.synpse.net/synpse-core/applications

func (*API) CreateJob

func (api *API) CreateJob(ctx context.Context, namespace string, job Job) (*Job, error)

func (*API) CreateNamespace

func (api *API) CreateNamespace(ctx context.Context, namespace Namespace) (*Namespace, error)

CreateNamespace creates a new namespace in the current project.

func (*API) CreateProject

func (api *API) CreateProject(ctx context.Context, project Project) (*Project, error)

CreateProject creates a new project for the user. Note: this API can only be called with personal access keys (https://cloud.synpse.net/access-keys) and cannot be used when using a Service Account that was created inside the projec

func (*API) CreateRegistrationToken

func (api *API) CreateRegistrationToken(ctx context.Context, registrationToken DeviceRegistrationToken) (*DeviceRegistrationToken, error)

func (*API) CreateSecret

func (api *API) CreateSecret(ctx context.Context, namespace string, secret Secret) (*Secret, error)

CreateSecret creates a secret in a specified namespace. Secret data will be encoded to base64 before sending to the API.

Secrets API ref: https://docs.synpse.net/synpse-core/applications/secrets

func (*API) DeleteApplication

func (api *API) DeleteApplication(ctx context.Context, namespace, name string) error

func (*API) DeleteDevice

func (api *API) DeleteDevice(ctx context.Context, device string) error

func (*API) DeleteJob

func (api *API) DeleteJob(ctx context.Context, namespace, name string) error

func (*API) DeleteNamespace

func (api *API) DeleteNamespace(ctx context.Context, namespace string) error

DeleteNamespace delete namespace and all applications, secrets within it

func (*API) DeleteRegistrationToken

func (api *API) DeleteRegistrationToken(ctx context.Context, registrationToken string) error

func (*API) DeleteSecret

func (api *API) DeleteSecret(ctx context.Context, namespace, name string) error

DeleteSecret deletes secret from the namespace

func (*API) DeviceApplicationLogs

func (api *API) DeviceApplicationLogs(ctx context.Context, namespace, applicationID string, opts LogsOpts) (io.ReadCloser, error)

DeviceApplicationLogs returns logs for the specified device and application.

func (*API) DeviceConnect

func (api *API) DeviceConnect(ctx context.Context, deviceID, port, hostname string) (net.Conn, error)

func (*API) DeviceJobLogs

func (api *API) DeviceJobLogs(ctx context.Context, namespace, jobID string, opts LogsOpts) (net.Conn, error)

func (*API) DeviceReboot

func (api *API) DeviceReboot(ctx context.Context, deviceID string) error

func (*API) DeviceSSH

func (api *API) DeviceSSH(ctx context.Context, deviceID string) (net.Conn, error)

func (*API) GetApplication

func (api *API) GetApplication(ctx context.Context, namespace, name string) (*Application, error)

GetApplication gets application by name.

func (*API) GetDefaultDeviceRegistrationToken

func (api *API) GetDefaultDeviceRegistrationToken(ctx context.Context, project string) (*DeviceRegistrationToken, error)

func (*API) GetDevice

func (api *API) GetDevice(ctx context.Context, device string) (*Device, error)

func (*API) GetJob

func (api *API) GetJob(ctx context.Context, namespace, name string) (*Job, error)

func (*API) GetNamespace

func (api *API) GetNamespace(ctx context.Context, namespace string) (*Namespace, error)

GetNamespace returns namespace by name

func (*API) GetSecret

func (api *API) GetSecret(ctx context.Context, namespace, name string) (*Secret, error)

GetSecret gets the secret. Client automatically attempts base64 decoding the secret data.

func (*API) ListApplications

func (api *API) ListApplications(ctx context.Context, req *ListApplicationsRequest) ([]*Application, error)

ListApplications lists applications in the specified namespace

func (*API) ListDeviceRegistrationTokens

func (api *API) ListDeviceRegistrationTokens(ctx context.Context, req *ListDeviceRegistrationTokensRequest) ([]*DeviceRegistrationToken, error)

func (*API) ListDevices

func (api *API) ListDevices(ctx context.Context, req *ListDevicesRequest) (*ListDevicesResponse, error)

func (*API) ListJobs

func (api *API) ListJobs(ctx context.Context, req ListJobsRequest) ([]*Job, error)

func (*API) ListNamespaces

func (api *API) ListNamespaces(ctx context.Context, req *ListNamespacesRequest) ([]*Namespace, error)

ListNamespaces list namespaces in the current project

func (*API) ListProjects

func (api *API) ListProjects(ctx context.Context, req *ListProjectsRequest) ([]Project, error)

ListProjects returns a list of projects that the user has access to. Note: this API can only be called with personal access keys (https://cloud.synpse.net/access-keys) and cannot be used when using a Service Account that was created inside the project.

func (*API) ListSecrets

func (api *API) ListSecrets(ctx context.Context, req *ListSecretsRequest) ([]*Secret, error)

ListSecrets lists all secrets in a namespace

func (*API) UpdateApplication

func (api *API) UpdateApplication(ctx context.Context, namespace string, p Application) (*Application, error)

UpdateApplication updates application. This will trigger a version bump on the server side which will redeploy application on all devices that the application is scheduled on.

func (*API) UpdateDevice

func (api *API) UpdateDevice(ctx context.Context, device Device) (*Device, error)

UpdateDevice can update device name and desired version

func (*API) UpdateJob

func (api *API) UpdateJob(ctx context.Context, namespace string, j Job) (*Job, error)

func (*API) UpdateNamespace

func (api *API) UpdateNamespace(ctx context.Context, namespace Namespace) (*Namespace, error)

UpdateNamespace updates namespace

func (*API) UpdateRegistrationToken

func (api *API) UpdateRegistrationToken(ctx context.Context, registrationToken DeviceRegistrationToken) (*DeviceRegistrationToken, error)

func (*API) UpdateSecret

func (api *API) UpdateSecret(ctx context.Context, namespace string, p Secret) (*Secret, error)

UpdateSecret updates a secret data in a specified namespace. Note that secret type cannot be changed.

type Action

type Action string
const (
	ActionGet    Action = "Get"
	ActionList   Action = "List"
	ActionDelete Action = "Delete"
	ActionUpdate Action = "Update"
	ActionCreate Action = "Create"

	ActionSSH      Action = "SSH"
	ActionViewLogs Action = "ViewLogs"
	ActionWipe     Action = "Wipe"
	ActionReboot   Action = "Reboot"
	ActionConnect  Action = "Connect"
)

type AgentSettings

type AgentSettings struct {
	AgentLogLevel            string `json:"agentLogLevel" yaml:"agentLogLevel"`
	DesiredAgentVersion      string `json:"desiredAgentVersion" yaml:"desiredAgentVersion"`
	DesiredAgentVersionForce bool   `json:"-" yaml:"-"` // TODO: Placeholder only so we can wire it in if needed from controller side. If this set to true agent will ignore downgrade checks
}

type Application

type Application struct {
	ID            string      `json:"id" yaml:"id"`
	Version       int64       `json:"version" yaml:"version"`             // Version is used to check application updated
	ConfigVersion int64       `json:"configVersion" yaml:"configVersion"` // config version is used on agent side only to indicate that the config has changed and application object needs to be redeployed.
	CreatedAt     time.Time   `json:"createdAt" yaml:"createdAt"`
	UpdatedAt     time.Time   `json:"updatedAt" yaml:"updatedAt"`
	ProjectID     string      `json:"projectId" yaml:"projectId"`
	NamespaceID   string      `json:"namespaceId" yaml:"namespaceId"`
	Name          string      `json:"name" yaml:"name"`
	Description   string      `json:"description,omitempty" yaml:"description,omitempty"`
	Type          RuntimeType `json:"type" yaml:"type"`
	Scheduling    Scheduling  `json:"scheduling" yaml:"scheduling"`

	Spec             ApplicationSpec             `json:"spec" yaml:"spec"`
	DeploymentStatus ApplicationDeploymentStatus `json:"deploymentStatus,omitempty" yaml:"deploymentStatus,omitempty"` // computed
}

Application is

type ApplicationDeploymentStatus

type ApplicationDeploymentStatus struct {
	Pending   int `json:"pending" yaml:"pending"`
	Available int `json:"available" yaml:"available"`
	Total     int `json:"total" yaml:"total"`
}

ApplicationDeploymentStatus - high level status of the application deployment progress, computed on-the-fly based on the stats from the application/device status and what the scheduler thinks should be deployed

type ApplicationSpec

type ApplicationSpec struct {
	// Specs are parsed based on Type in main application struct
	ContainerSpec []ContainerSpec `json:"containers,omitempty" yaml:"containers,omitempty" validate:"dive"`
}

type CPUInfo

type CPUInfo struct {
	BrandName      string `json:"brandName" yaml:"brandName"`           // Brand name reported by the CPU
	VendorString   string `json:"vendorString" yaml:"vendorString"`     // Raw vendor string.
	PhysicalCores  int    `json:"physicalCores" yaml:"physicalCores"`   // Number of physical processor cores in your CPU. Will be 0 if undetectable.
	ThreadsPerCore int    `json:"threadsPerCore" yaml:"threadsPerCore"` // Number of threads per physical core. Will be 1 if undetectable.
	LogicalCores   int    `json:"logicalCores" yaml:"logicalCores"`     // Number of physical cores times threads that can run on each core through the use of hyperthreading. Will be 0 if undetectable.
	Family         int    `json:"family" yaml:"family"`                 // CPU family number
	Model          int    `json:"model" yaml:"model"`                   // CPU model number
	Hz             int64  `json:"hz" yaml:"hz"`                         // Clock speed, if known, 0 otherwise. Will attempt to contain base clock speed.
}

type Config

type Config struct {
	Rules []Rule `json:"rules,omitempty" yaml:"rules,omitempty"`
}

type ContainerSpec

type ContainerSpec struct {
	// Container runtime
	Name             string      `json:"name,omitempty" yaml:"name,omitempty" codec:"name" validate:"name"`
	Image            string      `json:"image,omitempty" yaml:"image,omitempty" codec:"image"`
	Args             []string    `json:"args,omitempty" yaml:"args,omitempty" codec:"args"`
	Auth             *DockerAuth `json:"auth,omitempty" yaml:"auth,omitempty" codec:"auth"`
	CapAdd           []string    `json:"capAdd,omitempty" yaml:"capAdd,omitempty" codec:"cap_add"`
	CapDrop          []string    `json:"capDrop,omitempty" yaml:"capDrop,omitempty" codec:"cap_drop"`
	Command          string      `json:"command,omitempty" yaml:"command,omitempty" codec:"command"`
	GPUs             string      `json:"gpus,omitempty" yaml:"gpus,omitempty" codec:"gpus"` // Shortcut flag for the GPUs, to enable all gpus, specify 'all'
	Entrypoint       []string    `json:"entrypoint,omitempty" yaml:"entrypoint,omitempty" codec:"entrypoint"`
	ForcePull        bool        `json:"forcePull,omitempty" yaml:"forcePull,omitempty" codec:"force_pull"`
	Hostname         string      `json:"hostname,omitempty" yaml:"hostname,omitempty" codec:"hostname"`
	MemoryHardLimit  int64       `json:"memoryHardLimit,omitempty" yaml:"memoryHardLimit,omitempty" codec:"memory_hard_limit"`
	User             string      `json:"user,omitempty" yaml:"user,omitempty" codec:"user"`
	NetworkMode      NetworkMode `json:"networkMode,omitempty" yaml:"networkMode,omitempty" codec:"network_mode"`
	Ports            []string    `json:"ports,omitempty" yaml:"ports,omitempty" codec:"ports"` // Ports to expose like 8080:800
	Privileged       bool        `json:"privileged,omitempty" yaml:"privileged,omitempty" codec:"privileged"`
	ImagePullTimeout string      `json:"imagePullTimeout,omitempty" yaml:"imagePullTimeout,omitempty" codec:"image_pull_timeout"`
	SecurityOpt      []string    `json:"securityOpt,omitempty" yaml:"securityOpt,omitempty" codec:"security_opt"`
	ShmSize          int64       `json:"shmSize,omitempty" yaml:"shmSize,omitempty" codec:"shm_size"`
	Volumes          []string    `json:"volumes,omitempty" yaml:"volumes,omitempty" codec:"volumes"`
	VolumeDriver     string      `json:"volumeDriver,omitempty" yaml:"volumeDriver,omitempty" codec:"volume_driver"`
	WorkDir          string      `json:"workDir,omitempty" yaml:"workDir,omitempty" codec:"work_dir"`

	// synpse specific
	Environment   Environments  `json:"env,omitempty" yaml:"env,omitempty" validate:"dive"`
	Secrets       []SecretRef   `json:"secrets,omitempty" yaml:"secrets,omitempty"`
	RestartPolicy RestartPolicy `json:"restartPolicy,omitempty" yaml:"restartPolicy,omitempty"`
}

type Device

type Device struct {
	ID        string    `json:"id" yaml:"id"`
	CreatedAt time.Time `json:"createdAt" yaml:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt" yaml:"updatedAt"`
	ProjectID string    `json:"projectId" yaml:"projectId"`

	Name                 string            `json:"name" yaml:"name"`
	RegistrationTokenID  string            `json:"registrationTokenId" yaml:"registrationTokenId"`
	AgentSettings        AgentSettings     `json:"agentSettings" yaml:"agentSettings"`
	Info                 DeviceInfo        `json:"info" yaml:"info" gorm:"json"`
	LastSeenAt           time.Time         `json:"lastSeenAt" yaml:"lastSeenAt"`
	Status               DeviceStatus      `json:"status" yaml:"status"`
	Labels               map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
	EnvironmentVariables map[string]string `json:"environmentVariables,omitempty" yaml:"environmentVariables,omitempty"`

	Applications []*Application `json:"applications,omitempty" yaml:"applications,omitempty"`
}

type DeviceInfo

type DeviceInfo struct {
	DeviceID      string     `json:"deviceId" yaml:"deviceId"`
	AgentVersion  string     `json:"agentVersion" yaml:"agentVersion"`
	AgentLogLevel string     `json:"agentLogLevel" yaml:"agentLogLevel"`
	IPAddress     string     `json:"ipAddress" yaml:"ipAddress"`
	Architecture  string     `json:"architecture" yaml:"architecture"`
	Hostname      string     `json:"hostname" yaml:"hostname"`
	OSRelease     OSRelease  `json:"osRelease" yaml:"osRelease"`
	Docker        DockerInfo `json:"docker" yaml:"docker"`

	CPUInfo CPUInfo `json:"cpuInfo" yaml:"cpuInfo"`
}

type DeviceJob

type DeviceJob struct {
	ID           string           `json:"id" yaml:"id"`
	CreatedAt    time.Time        `json:"createdAt" yaml:"createdAt"`
	UpdatedAt    time.Time        `json:"updatedAt" yaml:"updatedAt"`
	DeviceID     string           `json:"deviceId" yaml:"deviceId"`
	JobID        string           `json:"jobId" yaml:"jobId"`
	ProjectID    string           `json:"projectId" yaml:"projectId"`
	NamespaceID  string           `json:"namespaceId" yaml:"namespaceId"`
	DesiredState DeviceJobState   `json:"desiredState" yaml:"desiredState"`
	State        DeviceJobState   `json:"state" yaml:"state"`
	StartedAt    time.Time        `json:"startedAt" yaml:"startedAt"`
	CompletedAt  time.Time        `json:"completedAt" yaml:"completedAt"`
	Statuses     WorkloadStatuses `json:"statuses" yaml:"statuses"` // Reported by the device
}

DeviceJob represents a single instance of the job running on a device. This should have a start time, individual container statuses and the completion.

When Job is created, scheduler creates a DeviceJob that is then being tracked by the individual device (scheduled via device bundle). Device then updates the job statuses.

type DeviceJobState

type DeviceJobState string

DeviceJobState is an overall state of the job. If at least a single underlying container is in a failed state, then the job is considered failed.

const (
	DeviceJobStatePending   DeviceJobState = "pending"
	DeviceJobStateRunning   DeviceJobState = "running"
	DeviceJobStateFailed    DeviceJobState = "failed"
	DeviceJobStateSucceeded DeviceJobState = "succeeded"
	DeviceJobStateStopped   DeviceJobState = "stopped"
)

type DeviceNamingStrategy

type DeviceNamingStrategy struct {
	Type DeviceNamingStrategyType `json:"type" yaml:"type"`
}

type DeviceNamingStrategyType

type DeviceNamingStrategyType string
const (
	DeviceNamingStrategyTypeDefault      DeviceNamingStrategyType = "default"
	DeviceNamingStrategyTypeFromHostname DeviceNamingStrategyType = "fromHostname"
)

type DeviceRegistrationToken

type DeviceRegistrationToken struct {
	ID                   string               `json:"id" yaml:"id"`
	CreatedAt            time.Time            `json:"createdAt" yaml:"createdAt"`
	UpdatedAt            time.Time            `json:"updatedAt" yaml:"updatedAt"`
	ProjectID            string               `json:"projectId" yaml:"projectId"`
	MaxRegistrations     *int                 `json:"maxRegistrations" yaml:"maxRegistrations"`
	Name                 string               `json:"name" yaml:"name"`
	Description          string               `json:"description" yaml:"description"`
	Labels               map[string]string    `json:"labels" yaml:"labels"`
	EnvironmentVariables map[string]string    `json:"environmentVariables" yaml:"environmentVariables"`
	NamingStrategy       DeviceNamingStrategy `json:"namingStrategy" yaml:"namingStrategy"`

	DeviceCount int `json:"deviceCount" yaml:"deviceCount"` // read-only
}

type DeviceStatus

type DeviceStatus string

type DockerAuth

type DockerAuth struct {
	Username string `json:"username,omitempty" yaml:"username,omitempty" codec:"username"`
	// Leave empty to get password from secret
	Password   string `json:"password,omitempty" yaml:"password,omitempty" codec:"password"`
	Email      string `json:"email,omitempty" yaml:"email,omitempty" codec:"email"`
	ServerAddr string `json:"serverAddress,omitempty" yaml:"serverAddress,omitempty" codec:"serverAddress"`
	// FromSecret populates password from secret
	FromSecret string `json:"fromSecret,omitempty" yaml:"fromSecret,omitempty" codec:"fromSecret"`
}

type DockerInfo

type DockerInfo struct {
	Version           string `json:"version" yaml:"version"`
	PrivilegedEnabled bool   `json:"privilegedEnabled" yaml:"privilegedEnabled"`
	BridgeIP          string `json:"bridgeIP" yaml:"bridgeIP"`
	Runtimes          string `json:"runtimes" yaml:"runtimes"`
	OSType            string `json:"osType" yaml:"osType"`
	Health            string `json:"health" yaml:"health"`
	HealthDescription string `json:"healthDescription" yaml:"healthDescription"`
}

type Effect

type Effect string

type Environment

type Environment struct {
	Name       string `json:"name" yaml:"name"`
	Value      string `json:"value,omitempty" yaml:"value,omitempty"`
	FromSecret string `json:"fromSecret,omitempty" yaml:"fromSecret,omitempty"`
}

type Environments

type Environments []Environment

ByAge implements sort.Interface for []Person based on the Age field.

func (Environments) Len

func (e Environments) Len() int

func (Environments) Less

func (e Environments) Less(i, j int) bool

func (Environments) Swap

func (e Environments) Swap(i, j int)

type Job

type Job struct {
	// Primary ID
	ID string `json:"id" yaml:"id"`

	Name         string         `json:"name" yaml:"name"`
	Description  string         `json:"description,omitempty" yaml:"description,omitempty"`
	Scheduling   Scheduling     `json:"scheduling" yaml:"scheduling"`
	Spec         JobSpec        `json:"spec" yaml:"spec" validate:"dive"`
	DesiredState DeviceJobState `json:"desiredState" yaml:"desiredState"`

	Version       int64          `json:"version" yaml:"version"`             // Version is used to check application updated
	ConfigVersion int64          `json:"configVersion" yaml:"configVersion"` // config version is used on agent side only to indicate that the config has changed and application object needs to be redeployed.
	CreatedAt     time.Time      `json:"createdAt" yaml:"createdAt"`
	UpdatedAt     time.Time      `json:"updatedAt" yaml:"updatedAt"`
	CompletedAt   time.Time      `json:"completedAt" yaml:"completedAt"` // last job instance on a device that finished running
	ProjectID     string         `json:"projectId" yaml:"projectId"`
	NamespaceID   string         `json:"namespaceId" yaml:"namespaceId"`
	State         DeviceJobState `json:"status" yaml:"status"` // Compute from device jobs on status updates
	DeviceJobs    []*DeviceJob   `json:"deviceJobs,omitempty" yaml:"deviceJobs,omitempty"`
}

Job is a one-off run of the container run, similar to k8s job or `docker run` without daemonization. For jobs, restart policy is always - "no", meaning that the container will not be restarted if it fails or finishes.

type JobSpec

type JobSpec struct {
	// Specs are parsed based on Type in main job struct
	ContainerSpec []ContainerSpec `json:"containers,omitempty" yaml:"containers,omitempty" validate:"dive"`
}

type ListApplicationsRequest

type ListApplicationsRequest struct {
	Namespace string `json:"namespace"`
}

type ListDeviceRegistrationTokensRequest

type ListDeviceRegistrationTokensRequest struct {
}

type ListDevicesRequest

type ListDevicesRequest struct {
	SearchQuery       string            // Search query, e.g. "power-plant-one"
	Labels            map[string]string // A map of labels to match
	PaginationOptions PaginationOptions
}

type ListDevicesResponse

type ListDevicesResponse struct {
	Devices    []*Device
	Pagination Pagination
}

type ListJobsRequest

type ListJobsRequest struct {
	Namespace string `json:"namespace"`
}

type ListNamespacesRequest

type ListNamespacesRequest struct{}

type ListProjectsRequest

type ListProjectsRequest struct{}

type ListSecretsRequest

type ListSecretsRequest struct {
	Namespace string
}

type Logger

type Logger interface {
	Printf(format string, v ...interface{})
}

Logger defines the interface this library needs to use logging This is a subset of the methods implemented in the log package

type LogsOpts

type LogsOpts struct {
	Container string
	Device    string
	Follow    bool
	Tail      int
}

LogsOpts is the structure that needs to be passed when getting application logs from the device.

type Membership

type Membership struct {
	UserID    string `json:"userId" yaml:"userId"` // composite key
	ProjectID string `json:"projectId" yaml:"projectId"`

	CreatedAt time.Time `json:"createdAt" yaml:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt" yaml:"updatedAt"`

	// extra data fields (optional)
	User    User    `json:"user,omitempty" yaml:"user,omitempty"`
	Project Project `json:"project,omitempty" yaml:"project,omitempty"`
	Roles   []Role  `json:"roles,omitempty" yaml:"roles,omitempty"`
}

type Namespace

type Namespace struct {
	ID               string           `json:"id" yaml:"id"`
	CreatedAt        time.Time        `json:"createdAt" yaml:"createdAt"`
	UpdatedAt        time.Time        `json:"updatedAt" yaml:"updatedAt"`
	ProjectID        string           `json:"projectId" yaml:"projectId"`
	Name             string           `json:"name" yaml:"name"`
	Config           *NamespaceConfig `json:"config,omitempty" yaml:"config,omitempty"`
	ApplicationCount int              `json:"applicationCount,omitempty" yaml:"applicationCount,omitempty"` // Read only
}

Namespace is used to separate applications and secrets that reside in the same project. Applications from multiple namespaces can be deployed on the same devices.

type NamespaceConfig

type NamespaceConfig struct {
	RegistryAuth DockerAuth `json:"registryAuthentication,omitempty" yaml:"registryAuthentication,omitempty"`
}

type NetworkMode

type NetworkMode string

type OSRelease

type OSRelease struct {
	PrettyName string `json:"prettyName" yaml:"prettyName"`
	Name       string `json:"name" yaml:"name"`
	VersionID  string `json:"versionId" yaml:"versionId"`
	Version    string `json:"version" yaml:"version"`
	ID         string `json:"id" yaml:"id"`
	IDLike     string `json:"idLike" yaml:"idLike"`
}

type Option

type Option func(*API) error

Option is a functional option for configuring the API client.

func WithAPIEndpointURL

func WithAPIEndpointURL(apiBaseURL string) Option

WithAPIEndpointURL overrides default Synpse API address. Default: "https://cloud.synpse.net/api"

func WithHTTPClient

func WithHTTPClient(client *http.Client) Option

WithHTTPClient accepts a custom *http.Client for making API calls.

func WithHeaders

func WithHeaders(headers http.Header) Option

WithHeaders allows you to set custom HTTP headers when making API calls (e.g. for satisfying HTTP proxies, or for debugging).

func WithLogger

func WithLogger(logger Logger) Option

WithLogger can be set if you want to get log output from this API instance By default no log output is emitted

func WithRetryPolicy

func WithRetryPolicy(maxRetries int, minRetryDelaySecs int, maxRetryDelaySecs int) Option

WithRetryPolicy applies a non-default number of retries and min/max retry delays This will be used when the client exponentially backs off after errored requests

func WithUserAgent

func WithUserAgent(userAgent string) Option

WithUserAgent can be set if you want to send a software name and version for HTTP access logs. It is recommended to set it in order to help future Customer Support diagnostics and prevent collateral damage by sharing generic User-Agent string with abusive users. E.g. "my-software/1.2.3". By default generic Go User-Agent is used.

type Pagination

type Pagination struct {
	NextPageToken     string
	PreviousPageToken string
	PageSize          int
	TotalItems        int
}

type PaginationOptions

type PaginationOptions struct {
	PageToken string
	PageSize  int
}

PaginationOptions specifies pagination options for the API client, it's used together with the endpoints that support pagination

type Project

type Project struct {
	ID        string    `json:"id" yaml:"id" gorm:"primaryKey"`
	CreatedAt time.Time `json:"createdAt" yaml:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt" yaml:"updatedAt"`
	Name      string    `json:"name" yaml:"name" gorm:"uniqueIndex" validate:"required,lowercase,userTitleRegex"`

	Quota ProjectQuota `json:"quota" yaml:"quota" gorm:"json"`

	// Extra data fields (optional)
	DeviceCount      int `json:"deviceCount" yaml:"deviceCount"`
	ApplicationCount int `json:"applicationCount" yaml:"applicationCount"`
	NamespaceCount   int `json:"namespaceCount" yaml:"namespaceCount"`
	SecretCount      int `json:"secretCount" yaml:"secretCount"`
}

type ProjectQuota

type ProjectQuota struct {
	Devices          int           `json:"devices" yaml:"devices"`
	Namespaces       int           `json:"namespaces" yaml:"namespaces"`
	Applications     int           `json:"applications" yaml:"applications"`
	Secrets          int           `json:"secrets" yaml:"secrets"`
	LogsRetention    time.Duration `json:"logsRetention" yaml:"logsRetention"`
	MetricsRetention time.Duration `json:"metricsRetention" yaml:"metricsRetention"`
}

type Resource

type Resource string

Resource represents resource type

const (
	ResourceProject                   Resource = "Project"
	ResourceSecret                    Resource = "Secret"
	ResourceNamespace                 Resource = "Namespace"
	ResourceRole                      Resource = "Role"
	ResourceMembership                Resource = "Membership"
	ResourceMembershipRoleBinding     Resource = "MembershipRoleBinding"
	ResourceServiceAccount            Resource = "ServiceAccount"
	ResourceServiceAccountAccessKey   Resource = "ServiceAccountAccessKey"
	ResourceServiceAccountRoleBinding Resource = "ServiceAccountRoleBinding"
	ResourceApplication               Resource = "Application"
	ResourceApplicationAllocation     Resource = "ApplicationAllocation" // Computed resource
	ResourceDevice                    Resource = "Device"
	ResourceDeviceRegistrationToken   Resource = "DeviceRegistrationToken"
	ResourceAny                       Resource = "*"
)

type RestartPolicy

type RestartPolicy struct {
	Name              string `json:"name,omitempty" yaml:"name,omitempty" toml:"name,omitempty"`
	MaximumRetryCount int    `json:"maximumRetryCount,omitempty" yaml:"maximumRetryCount,omitempty" toml:"maximumRetryCount,omitempty"`
}

func AlwaysRestart

func AlwaysRestart() RestartPolicy

AlwaysRestart returns a restart policy that tells the Docker daemon to always restart the container.

func NeverRestart

func NeverRestart() RestartPolicy

NeverRestart returns a restart policy that tells the Docker daemon to never restart the container on failures.

func RestartOnFailure

func RestartOnFailure(maxRetry int) RestartPolicy

RestartOnFailure returns a restart policy that tells the Docker daemon to restart the container on failures, trying at most maxRetry times.

func RestartUnlessStopped

func RestartUnlessStopped() RestartPolicy

RestartUnlessStopped returns a restart policy that tells the Docker daemon to always restart the container except when user has manually stopped the container.

type RetryPolicy

type RetryPolicy struct {
	MaxRetries    int
	MinRetryDelay time.Duration
	MaxRetryDelay time.Duration
}

RetryPolicy specifies number of retries and min/max retry delays This config is used when the client exponentially backs off after errored requests

type Role

type Role struct {
	ID          string    `json:"id" yaml:"id"`
	CreatedAt   time.Time `json:"createdAt" yaml:"createdAt"`
	UpdatedAt   time.Time `json:"updatedAt" yaml:"updatedAt"`
	ProjectID   string    `json:"projectId" yaml:"projectId"`
	Name        string    `json:"name" yaml:"name"`
	Description string    `json:"description" yaml:"description"`
	Config      Config    `json:"config" yaml:"config"`
}

type Rule

type Rule struct {
	Resources []Resource `json:"resource,omitempty" yaml:"resource,omitempty"`
	Actions   []Action   `json:"actions,omitempty" yaml:"actions,omitempty"`
	Effect    Effect     `json:"effect,omitempty" yaml:"effect,omitempty"`
}

type RuntimeType

type RuntimeType string
const (
	RuntimeContainer RuntimeType = "container"
	RuntimeSystemd   RuntimeType = "systemd"
)

type ScheduleType

type ScheduleType string

type Scheduling

type Scheduling struct {
	Type      ScheduleType      `json:"type"`
	Selectors map[string]string `json:"selectors"`
}

type Secret

type Secret struct {
	ID          string     `json:"id,omitempty" yaml:"id,omitempty"`
	CreatedAt   time.Time  `json:"createdAt,omitempty" yaml:"createdAt,omitempty"`
	UpdatedAt   time.Time  `json:"updatedAt,omitempty" yaml:"updatedAt,omitempty"`
	Name        string     `json:"name" yaml:"name"`
	ProjectID   string     `json:"projectId,omitempty" yaml:"projectId,omitempty"`
	NamespaceID string     `json:"namespaceId,omitempty" yaml:"namespaceId,omitempty"`
	Version     int64      `json:"version,omitempty" yaml:"version,omitempty"`
	Type        SecretType `json:"type,omitempty" yaml:"type,omitempty"`
	Data        string     `json:"data,omitempty" yaml:"data,omitempty"` // Base64 encoded data
}

Secret is used to conceal sensitive configuration from the deployment manifests. You can create multiple secrets per namespace and use them across one or more applications. Environment type secrets can be used for applications as environment variables or also can be used in Docker registry authentication.

type SecretRef

type SecretRef struct {
	Name string `json:"name" yaml:"name"`
	// Filepath specifies where the secret should be mounted
	// into a running container. This is used in the application spec itself and
	// not stored in the database
	Filepath string `json:"filepath,omitempty" yaml:"filepath,omitempty"`
}

type SecretType

type SecretType string
const (
	SecretTypeEnvironment SecretType = "Environment" // Can be used as environment variables
	SecretTypeFile        SecretType = "File"        // Can be mounted as a file to a container
)

type User

type User struct {
	ID        string    `json:"id" yaml:"id"`
	CreatedAt time.Time `json:"createdAt" yaml:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt" yaml:"updatedAt"`

	Name     string `json:"name,omitempty" yaml:"name,omitempty"`
	Email    string `json:"email,omitempty" yaml:"email,omitempty" `
	UserType string `json:"userType" yaml:"userType" gorm:"index"`

	// external users attributes
	ProviderName string            `json:"providerName,omitempty" yaml:"providerName,omitempty"`
	ProviderID   string            `json:"providerId,omitempty" yaml:"providerId,omitempty"`
	Info         map[string]string `json:"info,omitempty" yaml:"info,omitempty"`

	Quota UserQuota `json:"quota" yaml:"quota" gorm:"json"`
}

type UserQuota

type UserQuota struct {
	Projects int `json:"projects" yaml:"projects"`
}

type WorkloadState

type WorkloadState string

WorkloadState used to track current application/job state

const (
	// StatePending is initial state where healthy applications should be healthy but not yet
	// running. Retries are returned to this state too
	StatePending WorkloadState = "pending"
	// StateCreated is state before starting when container is created but not started yet
	StateCreated WorkloadState = "created"
	// StateRunning application is running and runtime is not complaining
	StateRunning WorkloadState = "running"
	// StateStopped is the state when runtime reports container to be stopped. This will retry
	StateStopped WorkloadState = "stopped"
	// StateDeleting is set when application is scheduled for deletion
	StateDeleting WorkloadState = "deleting"
	// StateFailed is terminal state. This will NOT retry
	StateFailed WorkloadState = "failed"
	// StateUnknown is the runtime state where we don't know the state. This will retry
	StateUnknown WorkloadState = "unknown"
	// StateExited is the runtime state where container exited with terminal code. This will retry
	StateExited WorkloadState = "exited"
)

Available ContainerState values

type WorkloadStatus

type WorkloadStatus struct {
	Name        string            `json:"name" yaml:"name"`
	State       WorkloadState     `json:"state" yaml:"state"`
	Message     string            `json:"message" yaml:"message"`
	Timestamp   time.Time         `json:"timestamp" yaml:"timestamp"`
	Annotations map[string]string `json:"annotations" yaml:"annotations"`
	StartedAt   time.Time         `json:"startedAt" yaml:"startedAt"`
	CompletedAt time.Time         `json:"completedAt" yaml:"completedAt"`
}

WorkloadStatus is part of the application/job status

type WorkloadStatuses

type WorkloadStatuses []WorkloadStatus

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL