devnet

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Dec 2, 2025 License: Apache-2.0 Imports: 43 Imported by: 0

Documentation

Index

Constants

View Source
const (
	LabelsKeyDomain          = "dz.malbeclabs.com"
	LabelsKeyType            = "type"
	LabelsKeyTypeValueDevnet = "devnet"
	LabelsKeyDeployID        = "deploy-id"
	LabelsFilterTypeDevnet   = LabelsKeyDomain + "/" + LabelsKeyType + "=" + LabelsKeyTypeValueDevnet
)

Variables

View Source
var (
	ErrDevicePubkeyNotFoundOnchain = errors.New("device pubkey not found onchain")
	ErrDeviceNotFoundOnchain       = errors.New("device not found onchain")
)

Functions

func BuildContainerImages

func BuildContainerImages(ctx context.Context, log *slog.Logger, workspaceDir string, verbose bool) error

func DeviceExecAristaCliJSON

func DeviceExecAristaCliJSON[T any](ctx context.Context, device *Device, command string) (T, error)

ExecCliReturnJSONObject executes a command on the device using the Cli tool and returns the JSON-encoded response as a map.

func LoadContainerImagesEnvFile

func LoadContainerImagesEnvFile(log *slog.Logger, workspaceDir string) error

func WorkspaceDir

func WorkspaceDir() (string, error)

Types

type Activator

type Activator struct {
	ContainerID string
	// contains filtered or unexported fields
}

func (*Activator) Exists

func (a *Activator) Exists(ctx context.Context) (bool, error)

Exists checks if the activator container exists.

func (*Activator) Start

func (a *Activator) Start(ctx context.Context) error

Start creates and starts the activator container and attaches it to the default network.

func (*Activator) StartIfNotRunning

func (a *Activator) StartIfNotRunning(ctx context.Context) (bool, error)

StartIfNotRunning creates and starts the activator container if it's not already running.

type ActivatorSpec

type ActivatorSpec struct {
	ContainerImage string
}

func (*ActivatorSpec) Validate

func (s *ActivatorSpec) Validate() error

type BuildConfig

type BuildConfig struct {
	Verbose bool
}

type CYOANetwork

type CYOANetwork struct {
	Name       string
	SubnetCIDR string
	// contains filtered or unexported fields
}

func (*CYOANetwork) Create

func (n *CYOANetwork) Create(ctx context.Context) error

func (*CYOANetwork) CreateIfNotExists

func (n *CYOANetwork) CreateIfNotExists(ctx context.Context) (bool, error)

func (*CYOANetwork) Exists

func (n *CYOANetwork) Exists(ctx context.Context) (bool, error)

type CYOANetworkSpec

type CYOANetworkSpec struct {
	CIDRPrefix int
}

func (*CYOANetworkSpec) Validate

func (s *CYOANetworkSpec) Validate() error

type Client

type Client struct {
	Spec *ClientSpec

	ContainerID   string
	Pubkey        string
	CYOANetworkIP string
	// contains filtered or unexported fields
}

func (*Client) Exec

func (c *Client) Exec(ctx context.Context, command []string, options ...docker.ExecOption) ([]byte, error)

func (*Client) ExecReturnJSONList

func (c *Client) ExecReturnJSONList(ctx context.Context, command []string, options ...docker.ExecOption) ([]map[string]any, error)

func (*Client) Exists

func (c *Client) Exists(ctx context.Context) (bool, error)

Exists checks if the ledger container exists.

func (*Client) GetTunnelStatus

func (c *Client) GetTunnelStatus(ctx context.Context) ([]ClientStatusResponse, error)

func (*Client) Start

func (c *Client) Start(ctx context.Context) error

func (*Client) StartIfNotRunning

func (c *Client) StartIfNotRunning(ctx context.Context) (bool, error)

StartIfNotRunning creates and starts the client container if it's not already running.

func (*Client) WaitForLatencyResults

func (c *Client) WaitForLatencyResults(ctx context.Context, wantDevicePK string, timeout time.Duration) error

func (*Client) WaitForTunnelDisconnected

func (c *Client) WaitForTunnelDisconnected(ctx context.Context, timeout time.Duration) error

func (*Client) WaitForTunnelStatus

func (c *Client) WaitForTunnelStatus(ctx context.Context, wantStatus ClientSessionStatus, timeout time.Duration) error

func (*Client) WaitForTunnelUp

func (c *Client) WaitForTunnelUp(ctx context.Context, timeout time.Duration) error

type ClientSession

type ClientSession struct {
	SessionStatus     ClientSessionStatus `json:"session_status"`
	LastSessionUpdate int64               `json:"last_session_update"`
}

type ClientSessionStatus

type ClientSessionStatus string
const (
	ClientSessionStatusUp           ClientSessionStatus = "up"
	ClientSessionStatusDown         ClientSessionStatus = "down"
	ClientSessionStatusDisconnected ClientSessionStatus = "disconnected"
)

type ClientSpec

type ClientSpec struct {
	ContainerImage string
	KeypairPath    string

	// Route liveness passive/active mode flags.
	// TODO(snormore): These flags are temporary for initial rollout testing.
	// They will be superceded by a single `route-liveness-enable` flag, where false means passive-mode
	// and true means active-mode.
	RouteLivenessEnablePassive bool
	RouteLivenessEnableActive  bool

	// RouteLivenessPeerMetrics is a flag to enable or disable per per-peer metrics for route
	// liveness (high cardinality).
	RouteLivenessPeerMetrics bool

	// RouteLivenessDebug is a flag to enable or disable debug logging for route liveness.
	RouteLivenessDebug bool

	// CYOANetworkIPHostID is the offset into the host portion of the subnet (must be < 2^(32 - prefixLen)).
	CYOANetworkIPHostID uint32
}

func (*ClientSpec) Validate

func (s *ClientSpec) Validate(cyoaNetworkSpec CYOANetworkSpec) error

type ClientStatusResponse

type ClientStatusResponse struct {
	TunnelName       string         `json:"tunnel_name"`
	TunnelSrc        net.IP         `json:"tunnel_src"`
	TunnelDst        net.IP         `json:"tunnel_dst"`
	DoubleZeroIP     net.IP         `json:"doublezero_ip"`
	DoubleZeroStatus ClientSession  `json:"doublezero_status"`
	UserType         ClientUserType `json:"user_type"`
}

type ClientUserType

type ClientUserType string

type Controller

type Controller struct {
	ContainerID      string
	ExternalPort     int
	DefaultNetworkIP string
	// contains filtered or unexported fields
}

func (*Controller) Exists

func (c *Controller) Exists(ctx context.Context) (bool, error)

Exists checks if the controller container exists.

func (*Controller) GetAgentConfig

func (c *Controller) GetAgentConfig(ctx context.Context, deviceAgentPubkey string) (*pb.ConfigResponse, error)

func (*Controller) Start

func (c *Controller) Start(ctx context.Context) error

func (*Controller) StartIfNotRunning

func (c *Controller) StartIfNotRunning(ctx context.Context) (bool, error)

StartIfNotRunning creates and starts the controller container if it's not already running.

type ControllerSpec

type ControllerSpec struct {
	ContainerImage string
}

func (*ControllerSpec) Validate

func (s *ControllerSpec) Validate(cyoaNetworkSpec CYOANetworkSpec) error

type DefaultNetwork

type DefaultNetwork struct {
	Name       string
	SubnetCIDR string
	// contains filtered or unexported fields
}

func (*DefaultNetwork) Create

func (n *DefaultNetwork) Create(ctx context.Context) error

func (*DefaultNetwork) CreateIfNotExists

func (n *DefaultNetwork) CreateIfNotExists(ctx context.Context) (bool, error)

func (*DefaultNetwork) Exists

func (n *DefaultNetwork) Exists(ctx context.Context) (bool, error)

type Device

type Device struct {
	Spec *DeviceSpec

	// ID is the PDA derived address/pubkey of the device onchain.
	// It's the primary key of the devices dataset in the ledger.
	ID string

	ContainerID   string
	CYOANetworkIP string

	// ExternalEAPIHTTPPort is the port on which the device's EAPI HTTP server is exposed.
	ExternalEAPIHTTPPort int

	// ExternalTelemetryMetricsPort is the port on which the device's telemetry metrics server is exposed.
	ExternalTelemetryMetricsPort int
	// contains filtered or unexported fields
}

func (*Device) Exec

func (d *Device) Exec(ctx context.Context, command []string) ([]byte, error)

func (*Device) Exists

func (d *Device) Exists(ctx context.Context) (bool, error)

Exists checks if the ledger container exists.

func (*Device) GetEAPIHTTPClient

func (d *Device) GetEAPIHTTPClient() (*goeapi.Node, error)

func (*Device) GetTelemetryMetricsClient

func (d *Device) GetTelemetryMetricsClient() *prometheus.MetricsClient

func (*Device) InternalTelemetryMetricsPort

func (d *Device) InternalTelemetryMetricsPort() (int, error)

func (*Device) Start

func (d *Device) Start(ctx context.Context) error

StartDevice starts a device container and attaches it to the management network.

Interface ordering very much matters with containerized EOS. The first network attached is the management interface, then subsequent networks correspond to ethernet interfaces.

Docker attaches interfaces in seemingly random order if the container is not yet started. If the networks end up attached in the wrong order, this test will fail as the CYOA network will not be attached to Ethernet1. To avoid this, we start the container with the default bridge network attached, then attach the CYOA network to the container.

func (*Device) StartIfNotRunning

func (d *Device) StartIfNotRunning(ctx context.Context) (bool, error)

StartIfNotRunning creates and starts the device container if it's not already running.

type DeviceSpec

type DeviceSpec struct {
	ContainerImage     string
	Code               string
	Location           string
	Exchange           string
	MetricsPublisherPK string

	// CYOANetworkIPHostID is the offset into the host portion of the subnet (must be < 2^(32 - prefixLen)).
	CYOANetworkIPHostID uint32

	// CYOANetworkAllocatablePrefix is the prefix length of the allocatable portion of the CYOA network.
	// This is used to derive the allocatable IP addresses for the device.
	CYOANetworkAllocatablePrefix uint32

	// Agent telemetry config.
	Telemetry DeviceTelemetrySpec

	// Additional docker networks to attach the device to.
	AdditionalNetworks []string

	// Interfaces is a map of interface names to types.
	Interfaces map[string]string

	// LoopbackInterfaces is a map of interface names to loopback types.
	LoopbackInterfaces map[string]string
}

func (*DeviceSpec) Validate

func (s *DeviceSpec) Validate(cyoaNetworkSpec CYOANetworkSpec) error

type DeviceTelemetrySpec

type DeviceTelemetrySpec struct {
	Enabled bool

	// KeypairPath is the path to the telemetry keypair.
	KeypairPath string

	// TWAMPListenPort is the port on which the device will listen for TWAMP probes.
	TWAMPListenPort uint16

	// ProbeInterval is the interval at which to probe peers.
	ProbeInterval time.Duration

	// SubmissionInterval is the interval at which to submit samples.
	SubmissionInterval time.Duration

	// PeersRefreshInterval is the interval at which to refresh peers.
	PeersRefreshInterval time.Duration

	// ManagementNS is the name of the management namespace to use for ledger communication.
	// If not provided, the default namespace will be used.
	ManagementNS string

	// Verbose is whether to enable verbose logging.
	Verbose bool

	// MetricsEnable is whether to enable prometheus metrics.
	MetricsEnable bool

	// MetricsAddr is the listen address for the prometheus metrics server.
	MetricsAddr string
}

func (*DeviceTelemetrySpec) Validate

func (s *DeviceTelemetrySpec) Validate() error

type Devnet

type Devnet struct {
	Spec DevnetSpec

	ExternalHost string

	DefaultNetwork *DefaultNetwork
	CYOANetwork    *CYOANetwork

	Ledger     *Ledger
	Manager    *Manager
	Funder     *Funder
	Controller *Controller
	Activator  *Activator
	Devices    map[string]*Device
	Clients    map[string]*Client
	// contains filtered or unexported fields
}

func New

func New(spec DevnetSpec, log *slog.Logger, dockerClient *client.Client, subnetAllocator *docker.SubnetAllocator) (*Devnet, error)

func (*Devnet) AddClient

func (d *Devnet) AddClient(ctx context.Context, spec ClientSpec) (*Client, error)

func (*Devnet) AddDevice

func (d *Devnet) AddDevice(ctx context.Context, spec DeviceSpec) (*Device, error)

func (*Devnet) Close

func (d *Devnet) Close()

func (*Devnet) CreateDeviceLoopbackInterface added in v0.5.3

func (d *Devnet) CreateDeviceLoopbackInterface(ctx context.Context, deviceCode string, interfaceName string, loopbackType string) error

func (*Devnet) CreateDeviceOnchain

func (d *Devnet) CreateDeviceOnchain(ctx context.Context, deviceCode string, location string, exchange string, publicIP string, prefixes []string, mgmtVrf string) error

func (*Devnet) DeleteDeviceLoopbackInterface added in v0.5.3

func (d *Devnet) DeleteDeviceLoopbackInterface(ctx context.Context, deviceCode string, interfaceName string) error

func (*Devnet) DeployServiceabilityProgram

func (dn *Devnet) DeployServiceabilityProgram(ctx context.Context) error

func (*Devnet) DeployServiceabilityProgramIfNotDeployed

func (dn *Devnet) DeployServiceabilityProgramIfNotDeployed(ctx context.Context) (bool, error)

func (*Devnet) DeployTelemetryProgram

func (dn *Devnet) DeployTelemetryProgram(ctx context.Context) error

func (*Devnet) DeployTelemetryProgramIfNotDeployed

func (dn *Devnet) DeployTelemetryProgramIfNotDeployed(ctx context.Context) (bool, error)

func (*Devnet) Destroy

func (d *Devnet) Destroy(ctx context.Context, all bool) error

func (*Devnet) GetDevicePubkeyOnchain

func (d *Devnet) GetDevicePubkeyOnchain(ctx context.Context, deviceCode string) (string, error)

func (*Devnet) GetOrCreateDeviceOnchain

func (d *Devnet) GetOrCreateDeviceOnchain(ctx context.Context, deviceCode string, location string, exchange string, metricsPublisherPK string, publicIP string, prefixes []string, mgmtVrf string) (string, error)

func (*Devnet) InitSmartContract

func (dn *Devnet) InitSmartContract(ctx context.Context) error

InitSmartContract initializes the smart contract using the manager container.

Perform the global state initialization via `doublezero init`, and then populate global config, location, and exchange information onchain.

func (*Devnet) InitSmartContractIfNotInitialized

func (dn *Devnet) InitSmartContractIfNotInitialized(ctx context.Context) (bool, error)

InitSmartContractIfNotInitialized initializes the smart contract if it's not already initialized.

func (*Devnet) IsServiceabilityProgramDeployed

func (dn *Devnet) IsServiceabilityProgramDeployed(ctx context.Context) (bool, error)

func (*Devnet) IsSmartContractInitialized

func (dn *Devnet) IsSmartContractInitialized(ctx context.Context) (bool, error)

IsSmartContractInitialized checks if the smart contract is initialized by checking for the presence of the default global configuration of any value.

func (*Devnet) IsTelemetryProgramDeployed

func (dn *Devnet) IsTelemetryProgramDeployed(ctx context.Context) (bool, error)

func (*Devnet) Start

func (d *Devnet) Start(ctx context.Context, buildConfig *BuildConfig) error

func (*Devnet) Stop

func (d *Devnet) Stop(ctx context.Context) error

type DevnetSpec

type DevnetSpec struct {
	DeployID  string
	DeployDir string

	// ExtraLabels are used to identify the resources created by the devnet.
	// These are added to the resources created by the devnet, in addition to default labels based
	// on the deployID.
	ExtraLabels map[string]string

	CYOANetwork CYOANetworkSpec

	// Override the default device tunnel network onchain.
	DeviceTunnelNet string
	Ledger          LedgerSpec
	Manager         ManagerSpec
	Funder          FunderSpec
	Controller      ControllerSpec
	Activator       ActivatorSpec
	Devices         map[string]DeviceSpec
	Clients         map[string]ClientSpec
}

func (*DevnetSpec) Validate

func (s *DevnetSpec) Validate() error

type Funder

type Funder struct {
	ContainerID         string
	ExternalMetricsPort int
	// contains filtered or unexported fields
}

func (*Funder) Exists

func (c *Funder) Exists(ctx context.Context) (bool, error)

Exists checks if the funder container exists.

func (*Funder) GetMetricsClient

func (c *Funder) GetMetricsClient() *prometheus.MetricsClient

func (*Funder) PrivateKey

func (c *Funder) PrivateKey() (solana.PrivateKey, error)

func (*Funder) Start

func (c *Funder) Start(ctx context.Context) error

func (*Funder) StartIfNotRunning

func (c *Funder) StartIfNotRunning(ctx context.Context) (bool, error)

StartIfNotRunning creates and starts the funder container if it's not already running.

type FunderSpec

type FunderSpec struct {
	ContainerImage  string
	KeypairPath     string
	Interval        time.Duration
	MinBalanceSOL   float64
	TopUpSOL        float64
	Verbose         bool
	ExtraRecipients map[string]string
}

func (*FunderSpec) Validate

func (s *FunderSpec) Validate() error

type Ledger

type Ledger struct {
	ContainerID      string
	InternalRPCURL   string
	InternalRPCWSURL string
	ExternalRPCPort  int

	// InternalIPRPCURL is the RPC URL of the ledger container using the internal IP instead of
	// hostname. This is needed by the device/agent which isn't able to use docker DNS.
	InternalIPRPCURL string
	// contains filtered or unexported fields
}

func (*Ledger) Exists

func (l *Ledger) Exists(ctx context.Context) (bool, error)

Exists checks if the ledger container exists.

func (*Ledger) GetRPCClient

func (l *Ledger) GetRPCClient() *rpc.Client

func (*Ledger) GetServiceabilityClient

func (l *Ledger) GetServiceabilityClient() (*serviceability.Client, error)

func (*Ledger) GetTelemetryClient

func (l *Ledger) GetTelemetryClient(signer *solana.PrivateKey) (*telemetry.Client, error)

func (*Ledger) Start

func (l *Ledger) Start(ctx context.Context) error

Start creates and starts the ledger container and attaches it to the default network.

func (*Ledger) StartIfNotRunning

func (l *Ledger) StartIfNotRunning(ctx context.Context) (bool, error)

StartIfNotRunning creates and starts the ledger container if it's not already running.

type LedgerSpec

type LedgerSpec struct {
	ContainerImage string
}

func (*LedgerSpec) Validate

func (s *LedgerSpec) Validate() error

type Manager

type Manager struct {
	ContainerID             string
	Pubkey                  string
	ServiceabilityProgramID string
	TelemetryProgramID      string
	// contains filtered or unexported fields
}

func (*Manager) Exec

func (m *Manager) Exec(ctx context.Context, command []string, opts ...docker.ExecOption) ([]byte, error)

func (*Manager) Exists

func (m *Manager) Exists(ctx context.Context) (bool, error)

Exists checks if the ledger container exists.

func (*Manager) Start

func (m *Manager) Start(ctx context.Context) error

Start creates and starts the manager container and attaches it to the default network.

func (*Manager) StartIfNotRunning

func (m *Manager) StartIfNotRunning(ctx context.Context) (bool, error)

StartIfNotRunning creates and starts the ledger container if it's not already running.

type ManagerSpec

type ManagerSpec struct {
	ContainerImage                   string
	ManagerKeypairPath               string
	ServiceabilityProgramKeypairPath string
	TelemetryProgramKeypairPath      string
}

func (*ManagerSpec) Validate

func (s *ManagerSpec) Validate() error

type MiscNetwork added in v0.5.3

type MiscNetwork struct {
	Name string
	// contains filtered or unexported fields
}

func NewMiscNetwork added in v0.5.3

func NewMiscNetwork(dn *Devnet, log *slog.Logger, suffix string) *MiscNetwork

func (*MiscNetwork) Create added in v0.5.3

func (n *MiscNetwork) Create(ctx context.Context) error

func (*MiscNetwork) CreateIfNotExists added in v0.5.3

func (n *MiscNetwork) CreateIfNotExists(ctx context.Context) (bool, error)

func (*MiscNetwork) Exists added in v0.5.3

func (n *MiscNetwork) Exists(ctx context.Context) (bool, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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