func/pkg/functions/instances.go

89 lines
2.7 KiB
Go

package functions
import (
"context"
"errors"
"fmt"
)
const (
EnvironmentLocal = "local"
EnvironmentRemote = "remote"
)
// InstanceRefs manager
//
// InstanceRefs are point-in-time snapshots of a function's runtime state in
// a given environment. By default 'local' and 'remote' environmnts are
// available when a function is run locally and deployed (respectively).
type InstanceRefs struct {
client *Client
}
// newInstances creates a new manager of instances.
func newInstances(client *Client) *InstanceRefs {
return &InstanceRefs{client: client}
}
// Get the instance data for a function in the named environment.
// For convenient access to the default 'local' and 'remote' environment
// see the Local and Remote methods, respectively.
// Instance returned is populated with a point-in-time snapshot of the
// function state in the named environment.
func (s *InstanceRefs) Get(ctx context.Context, f Function, environment string) (Instance, error) {
switch environment {
case EnvironmentLocal:
return s.Local(ctx, f)
case EnvironmentRemote:
return s.Remote(ctx, f.Name, f.Deploy.Namespace)
default:
// Future versions will support additional ad-hoc named environments, such
// as for testing. Local and remote remaining the base cases.
return Instance{}, ErrEnvironmentNotFound
}
}
// Local instance details for the function
// If the function is not running locally the error returned is ErrNotRunning
func (s *InstanceRefs) Local(ctx context.Context, f Function) (Instance, error) {
var i Instance
// To create a local instance the function must have a root path defined
// which contains an initialized function and be running.
if f.Root == "" {
return i, ErrRootRequired
}
if !f.Initialized() {
return i, ErrNotInitialized{f.Root}
}
ports := jobPorts(f)
if len(ports) == 0 {
return i, ErrNotRunning
}
route := fmt.Sprintf("http://localhost:%s/", ports[0])
return Instance{
Route: route,
Routes: []string{route},
Name: f.Name,
}, nil
}
// Remote instance details for the function
//
// Since this is specific to the implicitly available 'remote' environment, the
// request can be completed with either a name or the local source. Therefore
// either name or root path can be passed. If name is not passed, the function
// at root is loaded and its name used for describing the remote instance.
// Name takes precedence.
func (s *InstanceRefs) Remote(ctx context.Context, name, namespace string) (i Instance, err error) {
if name == "" {
return i, errors.New("fetching remote instances requires function name")
}
if namespace == "" {
return i, errors.New("fetching remote instances requires namespace")
}
return s.client.describer.Describe(ctx, name, namespace)
}