lib: Remove remote execution from core

I have an improved design for remote execution as a resource. Since I
need to get rid of some technical debt to clean up the resource API, and
this main loop, a good first step is to remote it's invocation. It will
be coming back as a resource as soon as possible!
This commit is contained in:
James Shubin
2018-02-28 17:45:48 -05:00
parent fdd698dade
commit ea52eb78d9
2 changed files with 1 additions and 132 deletions

View File

@@ -95,8 +95,6 @@ func run(c *cli.Context) error {
obj.Deploy = deployObj obj.Deploy = deployObj
} }
obj.Remotes = c.StringSlice("remote") // FIXME: GAPI-ify somehow?
obj.NoWatch = c.Bool("no-watch") obj.NoWatch = c.Bool("no-watch")
obj.NoConfigWatch = c.Bool("no-config-watch") obj.NoConfigWatch = c.Bool("no-config-watch")
obj.NoStreamWatch = c.Bool("no-stream-watch") obj.NoStreamWatch = c.Bool("no-stream-watch")
@@ -116,12 +114,6 @@ func run(c *cli.Context) error {
obj.IdealClusterSize = c.Int("ideal-cluster-size") obj.IdealClusterSize = c.Int("ideal-cluster-size")
obj.NoServer = c.Bool("no-server") obj.NoServer = c.Bool("no-server")
obj.CConns = uint16(c.Int("cconns"))
obj.AllowInteractive = c.Bool("allow-interactive")
obj.SSHPrivIDRsa = c.String("ssh-priv-id-rsa")
obj.NoCaching = c.Bool("no-caching")
obj.Depth = uint16(c.Int("depth"))
obj.NoPgp = c.Bool("no-pgp") obj.NoPgp = c.Bool("no-pgp")
if kp := c.String("pgp-key-path"); c.IsSet("pgp-key-path") { if kp := c.String("pgp-key-path"); c.IsSet("pgp-key-path") {
@@ -202,12 +194,6 @@ func CLI(program, version string, flags Flags) error {
Usage: "allow creation of a new temporary prefix if main prefix is unavailable", Usage: "allow creation of a new temporary prefix if main prefix is unavailable",
}, },
cli.StringSliceFlag{
Name: "remote",
Value: &cli.StringSlice{},
Usage: "list of remote graph definitions to run",
},
cli.BoolFlag{ cli.BoolFlag{
Name: "no-watch", Name: "no-watch",
Usage: "do not update graph under any switch events", Usage: "do not update graph under any switch events",
@@ -299,32 +285,6 @@ func CLI(program, version string, flags Flags) error {
Usage: "do not start embedded etcd server (do not promote from client to peer)", Usage: "do not start embedded etcd server (do not promote from client to peer)",
}, },
cli.IntFlag{
Name: "cconns",
Value: 0,
Usage: "number of maximum concurrent remote ssh connections to run; 0 for unlimited",
EnvVar: "MGMT_CCONNS",
},
cli.BoolFlag{
Name: "allow-interactive",
Usage: "allow interactive prompting, such as for remote passwords",
},
cli.StringFlag{
Name: "ssh-priv-id-rsa",
Value: "~/.ssh/id_rsa",
Usage: "default path to ssh key file, set empty to never touch",
EnvVar: "MGMT_SSH_PRIV_ID_RSA",
},
cli.BoolFlag{
Name: "no-caching",
Usage: "don't allow remote caching of remote execution binary",
},
cli.IntFlag{
Name: "depth",
Hidden: true, // internal use only
Value: 0,
Usage: "specify depth in remote hierarchy",
},
cli.BoolFlag{ cli.BoolFlag{
Name: "no-pgp", Name: "no-pgp",
Usage: "don't create pgp keys", Usage: "don't create pgp keys",

View File

@@ -32,8 +32,6 @@ import (
"github.com/purpleidea/mgmt/pgp" "github.com/purpleidea/mgmt/pgp"
"github.com/purpleidea/mgmt/pgraph" "github.com/purpleidea/mgmt/pgraph"
"github.com/purpleidea/mgmt/prometheus" "github.com/purpleidea/mgmt/prometheus"
"github.com/purpleidea/mgmt/recwatch"
"github.com/purpleidea/mgmt/remote"
"github.com/purpleidea/mgmt/resources" "github.com/purpleidea/mgmt/resources"
"github.com/purpleidea/mgmt/util" "github.com/purpleidea/mgmt/util"
@@ -64,7 +62,6 @@ type Main struct {
Deploy *gapi.Deploy // deploy object including GAPI for static deploys Deploy *gapi.Deploy // deploy object including GAPI for static deploys
DeployFs resources.Fs // used for static deploys DeployFs resources.Fs // used for static deploys
Remotes []string // list of remote graph definitions to run
NoWatch bool // do not change graph under any circumstances NoWatch bool // do not change graph under any circumstances
NoConfigWatch bool // do not update graph due to config changes NoConfigWatch bool // do not update graph due to config changes
@@ -85,12 +82,6 @@ type Main struct {
IdealClusterSize int // ideal number of server peers in cluster; only read by initial server IdealClusterSize int // ideal number of server peers in cluster; only read by initial server
NoServer bool // do not let other servers peer with me NoServer bool // do not let other servers peer with me
CConns uint16 // number of maximum concurrent remote ssh connections to run, 0 for unlimited
AllowInteractive bool // allow interactive prompting, such as for remote passwords
SSHPrivIDRsa string // default path to ssh key file, set empty to never touch
NoCaching bool // don't allow remote caching of remote execution binary
Depth uint16 // depth in remote hierarchy; for internal use only
seeds etcdtypes.URLs // processed seeds value seeds etcdtypes.URLs // processed seeds value
clientURLs etcdtypes.URLs // processed client urls value clientURLs etcdtypes.URLs // processed client urls value
serverURLs etcdtypes.URLs // processed server urls value serverURLs etcdtypes.URLs // processed server urls value
@@ -138,26 +129,6 @@ func (obj *Main) Init() error {
return fmt.Errorf("the IdealClusterSize should be at least one") return fmt.Errorf("the IdealClusterSize should be at least one")
} }
if obj.NoServer && len(obj.Remotes) > 0 {
// TODO: in this case, we won't be able to tunnel stuff back to
// here, so if we're okay with every remote graph running in an
// isolated mode, then this is okay. Improve on this if there's
// someone who really wants to be able to do this.
return fmt.Errorf("the Server is required when using Remotes")
}
if obj.CConns < 0 {
return fmt.Errorf("the CConns value should be at least zero")
}
if obj.ConvergedTimeout >= 0 && obj.CConns > 0 && len(obj.Remotes) > int(obj.CConns) {
return fmt.Errorf("you can't converge if you have more remotes than available connections")
}
if obj.Depth < 0 { // user should not be using this argument manually
return fmt.Errorf("negative values for Depth are not permitted")
}
// transform the url list inputs into etcd typed lists // transform the url list inputs into etcd typed lists
var err error var err error
obj.seeds, err = etcdtypes.NewURLs( obj.seeds, err = etcdtypes.NewURLs(
@@ -371,7 +342,7 @@ func (obj *Main) Run() error {
// root node. otherwise, if we are a child node in a remote // root node. otherwise, if we are a child node in a remote
// execution hierarchy, we should only notify our converged // execution hierarchy, we should only notify our converged
// state and wait for the parent to trigger the exit. // state and wait for the parent to trigger the exit.
if t := obj.ConvergedTimeout; obj.Depth == 0 && t >= 0 { if t := obj.ConvergedTimeout; t >= 0 {
if b { if b {
log.Printf("Main: Converged for %d seconds, exiting!", t) log.Printf("Main: Converged for %d seconds, exiting!", t)
obj.Exit(nil) // trigger an exit! obj.Exit(nil) // trigger an exit!
@@ -665,62 +636,6 @@ func (obj *Main) Run() error {
} }
}() }()
configWatcher := recwatch.NewConfigWatcher()
configWatcher.Flags = recwatch.Flags{Debug: obj.Flags.Debug}
events := configWatcher.Events()
if !obj.NoWatch { // FIXME: fit this into a clean GAPI?
configWatcher.Add(obj.Remotes...) // add all the files...
} else {
events = nil // signal that no-watch is true
}
go func() {
select {
case err := <-configWatcher.Error():
obj.Exit(err) // trigger an exit!
case <-exitchan:
return
}
}()
// initialize the add watcher, which calls the f callback on map changes
convergerCb := func(f func(map[string]bool) error) (func(), error) {
return etcd.AddHostnameConvergedWatcher(EmbdEtcd, f)
}
// build remotes struct for remote ssh
remotes := remote.NewRemotes(
EmbdEtcd.LocalhostClientURLs().StringSlice(),
[]string{etcd.DefaultClientURL},
obj.Noop,
obj.Remotes, // list of files
events, // watch for file changes
obj.CConns,
obj.AllowInteractive,
obj.SSHPrivIDRsa,
!obj.NoCaching,
obj.Depth,
prefix,
converger,
convergerCb,
remote.Flags{
Program: obj.Program,
Debug: obj.Flags.Debug,
},
)
// TODO: is there any benefit to running the remotes above in the loop?
// wait for etcd to be running before we remote in, which we do above!
go remotes.Run()
// wait for remotes to be ready before continuing...
select {
case <-remotes.Ready():
log.Printf("Main: Remotes: Run: Ready!")
// pass
//case <-time.After( ? * time.Second):
// obj.Exit(fmt.Errorf("Main: Remotes: Run timeout"))
}
if obj.Deploy != nil { if obj.Deploy != nil {
deploy := obj.Deploy deploy := obj.Deploy
// redundant // redundant
@@ -808,12 +723,6 @@ func (obj *Main) Run() error {
log.Println("Main: Destroy...") log.Println("Main: Destroy...")
configWatcher.Close() // stop sending file changes to remotes
if err := remotes.Exit(); err != nil { // tell all the remote connections to shutdown; waits!
err = errwrap.Wrapf(err, "the Remote exited poorly")
reterr = multierr.Append(reterr, err) // list of errors
}
// tell inner main loop to exit // tell inner main loop to exit
close(exitchan) close(exitchan)
wg.Wait() wg.Wait()