15028: Update to latest cwltool.
[arvados.git] / lib / cloud / interfaces.go
index c2b1acbabacb727d25be48b8a2b0c7b9d01916e5..792e737a914a1ce7d39d98c05c1a9428e77fb1ff 100644 (file)
@@ -5,11 +5,13 @@
 package cloud
 
 import (
-       "context"
+       "encoding/json"
+       "errors"
        "io"
        "time"
 
        "git.curoverse.com/arvados.git/sdk/go/arvados"
+       "github.com/sirupsen/logrus"
        "golang.org/x/crypto/ssh"
 )
 
@@ -56,18 +58,26 @@ type Executor interface {
        Execute(cmd string, stdin io.Reader) (stdout, stderr []byte, err error)
 }
 
+var ErrNotImplemented = errors.New("not implemented")
+
 // An ExecutorTarget is a remote command execution service.
 type ExecutorTarget interface {
        // SSH server hostname or IP address, or empty string if
        // unknown while instance is booting.
        Address() string
 
+       // Remote username to send during SSH authentication.
+       RemoteUser() string
+
        // Return nil if the given public key matches the instance's
        // SSH server key. If the provided Dialer is not nil,
        // VerifyHostKey can use it to make outgoing network
        // connections from the instance -- e.g., to use the cloud's
        // "this instance's metadata" API.
-       VerifyHostKey(context.Context, ssh.PublicKey, *ssh.Client) error
+       //
+       // Return ErrNotImplemented if no verification mechanism is
+       // available.
+       VerifyHostKey(ssh.PublicKey, *ssh.Client) error
 }
 
 // Instance is implemented by the provider-specific instance types.
@@ -89,10 +99,10 @@ type Instance interface {
        Tags() InstanceTags
 
        // Replace tags with the given tags
-       SetTags(context.Context, InstanceTags) error
+       SetTags(InstanceTags) error
 
        // Shut down the node
-       Destroy(context.Context) error
+       Destroy() error
 }
 
 // An InstanceSet manages a set of VM instances created by an elastic
@@ -101,12 +111,18 @@ type Instance interface {
 // All public methods of an InstanceSet, and all public methods of the
 // instances it returns, are goroutine safe.
 type InstanceSet interface {
-       // Create a new instance. If supported by the driver, add the
+       // Create a new instance with the given type, image, and
+       // initial set of tags. If supported by the driver, add the
        // provided public key to /root/.ssh/authorized_keys.
        //
+       // The given InitCommand should be executed on the newly
+       // created instance. This is optional for a driver whose
+       // instances' VerifyHostKey() method never returns
+       // ErrNotImplemented. InitCommand will be under 1 KiB.
+       //
        // The returned error should implement RateLimitError and
        // QuotaError where applicable.
-       Create(context.Context, arvados.InstanceType, ImageID, InstanceTags, ssh.PublicKey) (Instance, error)
+       Create(arvados.InstanceType, ImageID, InstanceTags, InitCommand, ssh.PublicKey) (Instance, error)
 
        // Return all instances, including ones that are booting or
        // shutting down. Optionally, filter out nodes that don't have
@@ -118,12 +134,14 @@ type InstanceSet interface {
        // Instance object each time. Thus, the caller is responsible
        // for de-duplicating the returned instances by comparing the
        // InstanceIDs returned by the instances' ID() methods.
-       Instances(context.Context, InstanceTags) ([]Instance, error)
+       Instances(InstanceTags) ([]Instance, error)
 
        // Stop any background tasks and release other resources.
        Stop()
 }
 
+type InitCommand string
+
 // A Driver returns an InstanceSet that uses the given InstanceSetID
 // and driver-dependent configuration parameters.
 //
@@ -153,9 +171,9 @@ type InstanceSet interface {
 //
 //     type exampleDriver struct {}
 //
-//     func (*exampleDriver) InstanceSet(config map[string]interface{}, id InstanceSetID) (InstanceSet, error) {
+//     func (*exampleDriver) InstanceSet(config json.RawMessage, id InstanceSetID) (InstanceSet, error) {
 //             var is exampleInstanceSet
-//             if err := mapstructure.Decode(config, &is); err != nil {
+//             if err := json.Unmarshal(config, &is); err != nil {
 //                     return nil, err
 //             }
 //             is.ownID = id
@@ -164,17 +182,17 @@ type InstanceSet interface {
 //
 //     var _ = registerCloudDriver("example", &exampleDriver{})
 type Driver interface {
-       InstanceSet(config map[string]interface{}, id InstanceSetID) (InstanceSet, error)
+       InstanceSet(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error)
 }
 
 // DriverFunc makes a Driver using the provided function as its
 // InstanceSet method. This is similar to http.HandlerFunc.
-func DriverFunc(fn func(config map[string]interface{}, id InstanceSetID) (InstanceSet, error)) Driver {
+func DriverFunc(fn func(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error)) Driver {
        return driverFunc(fn)
 }
 
-type driverFunc func(config map[string]interface{}, id InstanceSetID) (InstanceSet, error)
+type driverFunc func(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error)
 
-func (df driverFunc) InstanceSet(config map[string]interface{}, id InstanceSetID) (InstanceSet, error) {
-       return df(config, id)
+func (df driverFunc) InstanceSet(config json.RawMessage, id InstanceSetID, logger logrus.FieldLogger) (InstanceSet, error) {
+       return df(config, id, logger)
 }