Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple Sidekick functionality added. #33

Merged
merged 1 commit into from
Feb 27, 2018
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
41 changes: 17 additions & 24 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,6 @@ import (
"github.com/urfave/cli"
)

type Rancher struct {
URL string `json:"url"`
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key"`
Service string `json:"service"`
Image string `json:"docker_image"`
StartFirst bool `json:"start_first"`
Confirm bool `json:"confirm"`
Timeout int `json:"timeout"`
IntervalMillis int64 `json:"interval_millis"`
BatchSize int64 `json:"batch_size"`
}

var build string // build number set at compile-time

func main() {
Expand Down Expand Up @@ -52,6 +39,11 @@ func main() {
Usage: "Service to act on",
EnvVar: "PLUGIN_SERVICE",
},
cli.StringSliceFlag{
Name: "sidekick",
Usage: "Service's sidekick name and image separated by the space, supports multiple flags",
EnvVar: "PLUGIN_SIDEKICK",
},
cli.StringFlag{
Name: "docker-image",
Usage: "image to use",
Expand Down Expand Up @@ -99,17 +91,18 @@ func main() {

func run(c *cli.Context) error {
plugin := Plugin{
URL: c.String("url"),
Key: c.String("access-key"),
Secret: c.String("secret-key"),
Service: c.String("service"),
DockerImage: c.String("docker-image"),
StartFirst: c.BoolT("start-first"),
Confirm: c.Bool("confirm"),
Timeout: c.Int("timeout"),
IntervalMillis: c.Int64("interval-millis"),
BatchSize: c.Int64("batch-size"),
YamlVerified: c.BoolT("yaml-verified"),
URL: c.String("url"),
Key: c.String("access-key"),
Secret: c.String("secret-key"),
Service: c.String("service"),
SidekickDockerImage: c.StringSlice("sidekick"),
DockerImage: c.String("docker-image"),
StartFirst: c.BoolT("start-first"),
Confirm: c.Bool("confirm"),
Timeout: c.Int("timeout"),
IntervalMillis: c.Int64("interval-millis"),
BatchSize: c.Int64("batch-size"),
YamlVerified: c.BoolT("yaml-verified"),
}
return plugin.Exec()
}
67 changes: 49 additions & 18 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,27 @@ import (
)

type Plugin struct {
URL string
Key string
Secret string
Service string
DockerImage string
StartFirst bool
Confirm bool
Timeout int
IntervalMillis int64
BatchSize int64
YamlVerified bool
URL string
Key string
Secret string
Service string
SidekickDockerImage []string
DockerImage string
StartFirst bool
Confirm bool
Timeout int
IntervalMillis int64
BatchSize int64
YamlVerified bool
}

func (p *Plugin) Exec() error {
log.Info("Drone Rancher Plugin built")

if p.URL == "" || p.Key == "" || p.Secret == "" {
if p.URL == "" || p.Key == "" || p.Secret == "" || p.Service == "" {
return errors.New("Eek: Must have url, key, secret, and service definied")
}

if !strings.HasPrefix(p.DockerImage, "docker:") {
p.DockerImage = fmt.Sprintf("docker:%s", p.DockerImage)
}
var wantedService, wantedStack string
if strings.Contains(p.Service, "/") {
parts := strings.SplitN(p.Service, "/", 2)
Expand All @@ -58,6 +56,7 @@ func (p *Plugin) Exec() error {
// Query stacks with filter name=wantedStack
if wantedStack != "" {
stacks, err := rancher.Stack.List(&client.ListOpts{Filters: map[string]interface{}{"name": wantedStack}})

if err != nil {
return fmt.Errorf("Failed to list rancher environments: %s", err)
}
Expand All @@ -66,6 +65,7 @@ func (p *Plugin) Exec() error {
}
// If found add stackID to serviceFilters
serviceFilters["stackId"] = stacks.Data[0].Id

}

// Query services with prepared filters
Expand All @@ -77,9 +77,31 @@ func (p *Plugin) Exec() error {
return fmt.Errorf("Unable to find service %s", p.Service)
}
service := services.Data[0]

// Service is found, proceed with upgrade
service.LaunchConfig.ImageUuid = p.DockerImage

// We want to exit if there is no docker image updates
if p.DockerImage == "" && len(p.SidekickDockerImage) <= 0 {
return fmt.Errorf("Nothing to upgrade")
}

// Only change value if it's not null.
if p.DockerImage != "" {
// Add prefix when missing to meet Rancher API requirement
service.LaunchConfig.ImageUuid = prepareDockerPrefix(p.DockerImage)
}

// Iterate over provided sidekick flags
for _, sidekick := range p.SidekickDockerImage {
// Split flag in two from "--sidekick nginx nginx:latest"
parts := strings.SplitN(sidekick, " ", 2)
wantedSidekick := parts[0]
wantedImage := parts[1]
for i, s := range service.SecondaryLaunchConfigs {
if wantedSidekick == s.Name {
service.SecondaryLaunchConfigs[i].ImageUuid = prepareDockerPrefix(wantedImage)
}
}
}
upgrade := &client.ServiceUpgrade{}
upgrade.InServiceStrategy = &client.InServiceUpgradeStrategy{
LaunchConfig: service.LaunchConfig,
Expand All @@ -94,7 +116,6 @@ func (p *Plugin) Exec() error {
return fmt.Errorf("Unable to upgrade service %s: %s", p.Service, err)
}

log.Infof("Upgraded %s to %s", p.Service, p.DockerImage)
if p.Confirm {
srv, err := retry(func() (interface{}, error) {
s, e := rancher.Service.ById(service.Id)
Expand All @@ -117,11 +138,21 @@ func (p *Plugin) Exec() error {
}
log.Infof("Finished upgrade %s", p.Service)
}

log.Infof("Upgraded %s to %s", p.Service, p.DockerImage)

return nil
}

type retryFunc func() (interface{}, error)

func prepareDockerPrefix(image string) string {
if !strings.HasPrefix(image, "docker:") {
image = fmt.Sprintf("docker:%s", image)
}
return image
}

func retry(f retryFunc, timeout time.Duration, interval time.Duration) (interface{}, error) {
finish := time.After(timeout)
for {
Expand Down