Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.

[Experimental] - Max resource lifetime controller #545

Merged
merged 5 commits into from
May 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/infrakit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import (

// TODO - deprecate these in favor of the dynamic commands (see above)
//_ "github.com/docker/infrakit/cmd/infrakit/flavor"
//_ "github.com/docker/infrakit/cmd/infrakit/instance"
//_ "github.com/docker/infrakit/cmd/infrakit/group"
//_ "github.com/docker/infrakit/cmd/infrakit/instance"
//_ "github.com/docker/infrakit/cmd/infrakit/resource"

_ "github.com/docker/infrakit/cmd/infrakit/event"
Expand All @@ -32,6 +32,7 @@ import (
_ "github.com/docker/infrakit/cmd/infrakit/remote"
_ "github.com/docker/infrakit/cmd/infrakit/template"
_ "github.com/docker/infrakit/cmd/infrakit/util"
_ "github.com/docker/infrakit/cmd/infrakit/x"
)

func init() {
Expand Down
6 changes: 5 additions & 1 deletion cmd/infrakit/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ func Command(plugins func() discovery.Plugins) *cobra.Command {
Short: "Utilties",
}

util.AddCommand(muxCommand(plugins), fileServerCommand(plugins), trackCommand(plugins))
util.AddCommand(
muxCommand(plugins),
fileServerCommand(plugins),
trackCommand(plugins),
)

return util
}
99 changes: 99 additions & 0 deletions cmd/infrakit/x/maxlife.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package x

import (
"os"
"strings"
"time"

"github.com/docker/infrakit/pkg/discovery"
"github.com/docker/infrakit/pkg/plugin"
instance_rpc "github.com/docker/infrakit/pkg/rpc/instance"
"github.com/docker/infrakit/pkg/spi/instance"
"github.com/docker/infrakit/pkg/x/maxlife"
"github.com/spf13/cobra"
)

func maxlifeCommand(plugins func() discovery.Plugins) *cobra.Command {

cmd := &cobra.Command{
Use: "maxlife <instance plugin name>...",
Short: "Sets max life on the given instances",
}

//name := cmd.Flags().String("name", "", "Name to use as name of this plugin")
poll := cmd.Flags().DurationP("poll", "i", 10*time.Second, "Polling interval")
maxlifeDuration := cmd.Flags().DurationP("maxlife", "m", 10*time.Minute, "Max lifetime of the resource")
flagTags := cmd.Flags().StringSliceP("tag", "t", []string{}, "Tags to filter instance by")

cmd.RunE = func(c *cobra.Command, args []string) error {

if len(args) == 0 {
cmd.Usage()
os.Exit(-1)
}

tags := toTags(*flagTags)

// Now we have a list of instance plugins to maxlife
plugins, err := getInstancePlugins(plugins, args)
if err != nil {
return err
}

// For each we start a goroutine to poll and kill instances
controllers := []*maxlife.Controller{}

for name, plugin := range plugins {

controller := maxlife.NewController(name, plugin, *poll, *maxlifeDuration, tags)
controller.Start()

controllers = append(controllers, controller)
}

// TODO - publish events when we start taking down instances.
done := make(chan struct{})

<-done
return nil
}

return cmd
}

func ensureMaxlife(name string, plugin instance.Plugin, stop chan struct{}, poll, maxlife time.Duration,
tags map[string]string, initialCount int) {
}
func getInstancePlugins(plugins func() discovery.Plugins, names []string) (map[string]instance.Plugin, error) {
targets := map[string]instance.Plugin{}
for _, target := range names {
endpoint, err := plugins().Find(plugin.Name(target))
if err != nil {
return nil, err
}
if p, err := instance_rpc.NewClient(plugin.Name(target), endpoint.Address); err == nil {
targets[target] = p
} else {
return nil, err
}
}
return targets, nil
}

func toTags(slice []string) map[string]string {
tags := map[string]string{}

for _, tag := range slice {
kv := strings.SplitN(tag, "=", 2)
if len(kv) != 2 {
log.Warn("bad format tag", "input", tag)
continue
}
key := strings.TrimSpace(kv[0])
val := strings.TrimSpace(kv[1])
if key != "" && val != "" {
tags[key] = val
}
}
return tags
}
29 changes: 29 additions & 0 deletions cmd/infrakit/x/x.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package x

import (
"github.com/docker/infrakit/cmd/infrakit/base"
"github.com/docker/infrakit/pkg/discovery"
logutil "github.com/docker/infrakit/pkg/log"
"github.com/spf13/cobra"
)

var log = logutil.New("module", "cli/x")

func init() {
base.Register(Command)
}

// Command is the head of this module
func Command(plugins func() discovery.Plugins) *cobra.Command {

experimental := &cobra.Command{
Use: "x",
Short: "Experimental features",
}

experimental.AddCommand(
maxlifeCommand(plugins),
)

return experimental
}
41 changes: 32 additions & 9 deletions pkg/types/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,42 @@ func init() {
type Link struct {
value string
context string
created time.Time
}

// NewLink creates a link
func NewLink() *Link {
return &Link{
value: randomAlphaNumericString(16),
value: randomAlphaNumericString(16),
created: time.Now(),
}
}

// NewLinkFromMap constructs a link from data in the map
// Link related labels
const (
LinkLabel = "infrakit-link"
LinkContextLabel = "infrakit-link-context"
LinkCreatedLabel = "infrakit-link-created"
)

// NewLinkFromMap constructs a link from data in the map. The link will have missing data
// if the input does not contain the attribute labels.
func NewLinkFromMap(m map[string]string) *Link {
l := &Link{}
if v, has := m["infrakit-link"]; has {
if v, has := m[LinkLabel]; has {
l.value = v
}

if v, has := m["infrakit-link-context"]; has {
if v, has := m[LinkContextLabel]; has {
l.context = v
}

if v, has := m[LinkCreatedLabel]; has {
t, err := time.Parse(time.RFC3339, v)
if err == nil {
l.created = t
}
}
return l
}

Expand All @@ -52,9 +69,14 @@ func (l Link) Value() string {
return l.value
}

// Created returns the creation time of the link
func (l Link) Created() time.Time {
return l.created
}

// Label returns the label to look for the link
func (l Link) Label() string {
return "infrakit-link"
return LinkLabel
}

// Context returns the context of the link
Expand All @@ -80,8 +102,9 @@ func (l *Link) KVPairs() []string {
// Map returns a representation that is easily converted to JSON or YAML
func (l *Link) Map() map[string]string {
return map[string]string{
"infrakit-link": l.value,
"infrakit-link-context": l.context,
LinkLabel: l.value,
LinkContextLabel: l.context,
LinkCreatedLabel: l.created.Format(time.RFC3339),
}
}

Expand All @@ -94,15 +117,15 @@ func (l *Link) WriteMap(target map[string]string) {

// InMap returns true if the link is contained in the map
func (l *Link) InMap(m map[string]string) bool {
c, has := m["infrakit-link-context"]
c, has := m[LinkContextLabel]
if !has {
return false
}
if c != l.context {
return false
}

v, has := m["infrakit-link"]
v, has := m[LinkLabel]
if !has {
return false
}
Expand Down
Loading