diff --git a/glide.lock b/glide.lock index a6eb38fcf..710f91ced 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 1aa32496b865dda72d76c7cba3458f1c2c467acf0b99aab4609323f109aa64f6 -updated: 2017-05-02T11:46:23.91434995-04:00 +updated: 2017-05-19T23:30:19.890844996+02:00 imports: - name: cloud.google.com/go version: 2e6a95edb1071d750f6d7db777bf66cd2997af6c @@ -201,7 +201,7 @@ imports: - name: github.com/fatih/color version: 9131ab34cf20d2f6d83fdc67168a5430d1c7dc23 - name: github.com/gambol99/go-marathon - version: d672c6fbb499596869d95146a26e7d0746c06c54 + version: 15ea23e360abb8b25071e677aed344f31838e403 - name: github.com/ghodss/yaml version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee - name: github.com/go-ini/ini diff --git a/vendor/github.com/gambol99/go-marathon/application.go b/vendor/github.com/gambol99/go-marathon/application.go index 62eb24705..aba8dc77c 100644 --- a/vendor/github.com/gambol99/go-marathon/application.go +++ b/vendor/github.com/gambol99/go-marathon/application.go @@ -89,6 +89,8 @@ type Application struct { TaskStats map[string]TaskStats `json:"taskStats,omitempty"` User string `json:"user,omitempty"` UpgradeStrategy *UpgradeStrategy `json:"upgradeStrategy,omitempty"` + UnreachableStrategy *UnreachableStrategy `json:"unreachableStrategy,omitempty"` + KillSelection string `json:"killSelection,omitempty"` Uris *[]string `json:"uris,omitempty"` Version string `json:"version,omitempty"` VersionInfo *VersionInfo `json:"versionInfo,omitempty"` @@ -453,7 +455,7 @@ func (r *Application) DeploymentIDs() []*DeploymentID { // CheckHTTP adds a HTTP check to an application // port: the port the check should be checking // interval: the interval in seconds the check should be performed -func (r *Application) CheckHTTP(uri string, port, interval int) (*Application, error) { +func (r *Application) CheckHTTP(path string, port, interval int) (*Application, error) { if r.Container == nil || r.Container.Docker == nil { return nil, ErrNoApplicationContainer } @@ -464,7 +466,7 @@ func (r *Application) CheckHTTP(uri string, port, interval int) (*Application, e } health := NewDefaultHealthCheck() health.IntervalSeconds = interval - *health.Path = uri + *health.Path = path *health.PortIndex = portIndex // step: add to the checks r.AddHealthCheck(*health) @@ -555,6 +557,20 @@ func (r *Application) EmptyUpgradeStrategy() *Application { return r } +// SetUnreachableStrategy sets the unreachable strategy. +func (r *Application) SetUnreachableStrategy(us UnreachableStrategy) *Application { + r.UnreachableStrategy = &us + return r +} + +// EmptyUnreachableStrategy explicitly empties the unreachable strategy -- use this if +// you need to empty the unreachable strategy of an application that already has +// the unreachable strategy set (setting it to nil will keep the current value). +func (r *Application) EmptyUnreachableStrategy() *Application { + r.UnreachableStrategy = &UnreachableStrategy{} + return r +} + // String returns the json representation of this application func (r *Application) String() string { s, err := json.MarshalIndent(r, "", " ") @@ -611,9 +627,9 @@ func (r *marathonClient) HasApplicationVersion(name, version string) (bool, erro // ApplicationVersions is a list of versions which has been deployed with marathon for a specific application // name: the id used to identify the application func (r *marathonClient) ApplicationVersions(name string) (*ApplicationVersions, error) { - uri := fmt.Sprintf("%s/versions", buildURI(name)) + path := fmt.Sprintf("%s/versions", buildPath(name)) versions := new(ApplicationVersions) - if err := r.apiGet(uri, nil, versions); err != nil { + if err := r.apiGet(path, nil, versions); err != nil { return nil, err } return versions, nil @@ -623,9 +639,9 @@ func (r *marathonClient) ApplicationVersions(name string) (*ApplicationVersions, // name: the id used to identify the application // version: the version (normally a timestamp) you wish to change to func (r *marathonClient) SetApplicationVersion(name string, version *ApplicationVersion) (*DeploymentID, error) { - uri := fmt.Sprintf(buildURI(name)) + path := fmt.Sprintf(buildPath(name)) deploymentID := new(DeploymentID) - if err := r.apiPut(uri, version, deploymentID); err != nil { + if err := r.apiPut(path, version, deploymentID); err != nil { return nil, err } @@ -639,7 +655,7 @@ func (r *marathonClient) Application(name string) (*Application, error) { Application *Application `json:"app"` } - if err := r.apiGet(buildURI(name), nil, &wrapper); err != nil { + if err := r.apiGet(buildPath(name), nil, &wrapper); err != nil { return nil, err } @@ -650,7 +666,7 @@ func (r *marathonClient) Application(name string) (*Application, error) { // name: the id used to identify the application // opts: GetAppOpts request payload func (r *marathonClient) ApplicationBy(name string, opts *GetAppOpts) (*Application, error) { - u, err := addOptions(buildURI(name), opts) + path, err := addOptions(buildPath(name), opts) if err != nil { return nil, err } @@ -658,7 +674,7 @@ func (r *marathonClient) ApplicationBy(name string, opts *GetAppOpts) (*Applicat Application *Application `json:"app"` } - if err := r.apiGet(u, nil, &wrapper); err != nil { + if err := r.apiGet(path, nil, &wrapper); err != nil { return nil, err } @@ -671,8 +687,8 @@ func (r *marathonClient) ApplicationBy(name string, opts *GetAppOpts) (*Applicat func (r *marathonClient) ApplicationByVersion(name, version string) (*Application, error) { app := new(Application) - uri := fmt.Sprintf("%s/versions/%s", buildURI(name), version) - if err := r.apiGet(uri, nil, app); err != nil { + path := fmt.Sprintf("%s/versions/%s", buildPath(name), version) + if err := r.apiGet(path, nil, app); err != nil { return nil, err } @@ -779,10 +795,10 @@ func (r *marathonClient) appExistAndRunning(name string) bool { // name: the id used to identify the application // force: used to force the delete operation in case of blocked deployment func (r *marathonClient) DeleteApplication(name string, force bool) (*DeploymentID, error) { - uri := buildURIWithForceParam(name, force) + path := buildPathWithForceParam(name, force) // step: check of the application already exists deployID := new(DeploymentID) - if err := r.apiDelete(uri, nil, deployID); err != nil { + if err := r.apiDelete(path, nil, deployID); err != nil { return nil, err } @@ -794,8 +810,8 @@ func (r *marathonClient) DeleteApplication(name string, force bool) (*Deployment func (r *marathonClient) RestartApplication(name string, force bool) (*DeploymentID, error) { deployment := new(DeploymentID) var options struct{} - uri := buildURIWithForceParam(fmt.Sprintf("%s/restart", name), force) - if err := r.apiPost(uri, &options, deployment); err != nil { + path := buildPathWithForceParam(fmt.Sprintf("%s/restart", name), force) + if err := r.apiPost(path, &options, deployment); err != nil { return nil, err } @@ -810,9 +826,9 @@ func (r *marathonClient) ScaleApplicationInstances(name string, instances int, f changes := new(Application) changes.ID = validateID(name) changes.Instances = &instances - uri := buildURIWithForceParam(name, force) + path := buildPathWithForceParam(name, force) deployID := new(DeploymentID) - if err := r.apiPut(uri, changes, deployID); err != nil { + if err := r.apiPut(path, changes, deployID); err != nil { return nil, err } @@ -823,22 +839,22 @@ func (r *marathonClient) ScaleApplicationInstances(name string, instances int, f // application: the structure holding the application configuration func (r *marathonClient) UpdateApplication(application *Application, force bool) (*DeploymentID, error) { result := new(DeploymentID) - uri := buildURIWithForceParam(application.ID, force) - if err := r.apiPut(uri, application, result); err != nil { + path := buildPathWithForceParam(application.ID, force) + if err := r.apiPut(path, application, result); err != nil { return nil, err } return result, nil } -func buildURIWithForceParam(path string, force bool) string { - uri := buildURI(path) +func buildPathWithForceParam(rootPath string, force bool) string { + path := buildPath(rootPath) if force { - uri += "?force=true" + path += "?force=true" } - return uri + return path } -func buildURI(path string) string { +func buildPath(path string) string { return fmt.Sprintf("%s/%s", marathonAPIApps, trimRootPath(path)) } diff --git a/vendor/github.com/gambol99/go-marathon/client.go b/vendor/github.com/gambol99/go-marathon/client.go index b83d66711..d3ca78f8c 100644 --- a/vendor/github.com/gambol99/go-marathon/client.go +++ b/vendor/github.com/gambol99/go-marathon/client.go @@ -27,6 +27,7 @@ import ( "net/http" "net/url" "regexp" + "strings" "sync" "time" ) @@ -238,23 +239,23 @@ func (r *marathonClient) Ping() (bool, error) { return true, nil } -func (r *marathonClient) apiGet(uri string, post, result interface{}) error { - return r.apiCall("GET", uri, post, result) +func (r *marathonClient) apiGet(path string, post, result interface{}) error { + return r.apiCall("GET", path, post, result) } -func (r *marathonClient) apiPut(uri string, post, result interface{}) error { - return r.apiCall("PUT", uri, post, result) +func (r *marathonClient) apiPut(path string, post, result interface{}) error { + return r.apiCall("PUT", path, post, result) } -func (r *marathonClient) apiPost(uri string, post, result interface{}) error { - return r.apiCall("POST", uri, post, result) +func (r *marathonClient) apiPost(path string, post, result interface{}) error { + return r.apiCall("POST", path, post, result) } -func (r *marathonClient) apiDelete(uri string, post, result interface{}) error { - return r.apiCall("DELETE", uri, post, result) +func (r *marathonClient) apiDelete(path string, post, result interface{}) error { + return r.apiCall("DELETE", path, post, result) } -func (r *marathonClient) apiCall(method, url string, body, result interface{}) error { +func (r *marathonClient) apiCall(method, path string, body, result interface{}) error { for { // step: marshall the request to json var requestBody []byte @@ -266,7 +267,7 @@ func (r *marathonClient) apiCall(method, url string, body, result interface{}) e } // step: create the API request - request, member, err := r.buildAPIRequest(method, url, bytes.NewReader(requestBody)) + request, member, err := r.buildAPIRequest(method, path, bytes.NewReader(requestBody)) if err != nil { return err } @@ -317,7 +318,7 @@ func (r *marathonClient) apiCall(method, url string, body, result interface{}) e } // buildAPIRequest creates a default API request -func (r *marathonClient) buildAPIRequest(method, uri string, reader io.Reader) (request *http.Request, member string, err error) { +func (r *marathonClient) buildAPIRequest(method, path string, reader io.Reader) (request *http.Request, member string, err error) { // Grab a member from the cluster member, err = r.hosts.getMember() if err != nil { @@ -325,16 +326,22 @@ func (r *marathonClient) buildAPIRequest(method, uri string, reader io.Reader) ( } // Build the HTTP request to Marathon - request, err = r.client.buildMarathonRequest(method, member, uri, reader) + request, err = r.client.buildMarathonRequest(method, member, path, reader) if err != nil { return nil, member, err } return request, member, nil } -func (rc *httpClient) buildMarathonRequest(method string, member string, uri string, reader io.Reader) (request *http.Request, err error) { +// buildMarathonRequest creates a new HTTP request and configures it according to the *httpClient configuration. +// The path must not contain a leading "/", otherwise buildMarathonRequest will panic. +func (rc *httpClient) buildMarathonRequest(method string, member string, path string, reader io.Reader) (request *http.Request, err error) { + if strings.HasPrefix(path, "/") { + panic(fmt.Sprintf("Path '%s' must not start with a leading slash", path)) + } + // Create the endpoint URL - url := fmt.Sprintf("%s/%s", member, uri) + url := fmt.Sprintf("%s/%s", member, path) // Instantiate an HTTP request request, err = http.NewRequest(method, url, reader) diff --git a/vendor/github.com/gambol99/go-marathon/cluster.go b/vendor/github.com/gambol99/go-marathon/cluster.go index c7ea0a429..a97a22c53 100644 --- a/vendor/github.com/gambol99/go-marathon/cluster.go +++ b/vendor/github.com/gambol99/go-marathon/cluster.go @@ -131,7 +131,7 @@ func (c *cluster) markDown(endpoint string) { func (c *cluster) healthCheckNode(node *member) { // step: wait for the node to become active ... we are assuming a /ping is enough here for { - req, err := c.client.buildMarathonRequest("GET", node.endpoint, "/ping", nil) + req, err := c.client.buildMarathonRequest("GET", node.endpoint, "ping", nil) if err == nil { res, err := c.client.Do(req) if err == nil && res.StatusCode == 200 { diff --git a/vendor/github.com/gambol99/go-marathon/group.go b/vendor/github.com/gambol99/go-marathon/group.go index 2cdf2acac..b95e40328 100644 --- a/vendor/github.com/gambol99/go-marathon/group.go +++ b/vendor/github.com/gambol99/go-marathon/group.go @@ -106,12 +106,12 @@ func (r *marathonClient) Group(name string) (*Group, error) { // GroupsBy retrieves a list of all the groups from marathon by embed options // opts: GetGroupOpts request payload func (r *marathonClient) GroupsBy(opts *GetGroupOpts) (*Groups, error) { - u, err := addOptions(marathonAPIGroups, opts) + path, err := addOptions(marathonAPIGroups, opts) if err != nil { return nil, err } groups := new(Groups) - if err := r.apiGet(u, "", groups); err != nil { + if err := r.apiGet(path, "", groups); err != nil { return nil, err } return groups, nil @@ -121,12 +121,12 @@ func (r *marathonClient) GroupsBy(opts *GetGroupOpts) (*Groups, error) { // name: the identifier for the group // opts: GetGroupOpts request payload func (r *marathonClient) GroupBy(name string, opts *GetGroupOpts) (*Group, error) { - u, err := addOptions(fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)), opts) + path, err := addOptions(fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)), opts) if err != nil { return nil, err } group := new(Group) - if err := r.apiGet(u, nil, group); err != nil { + if err := r.apiGet(path, nil, group); err != nil { return nil, err } return group, nil @@ -135,8 +135,8 @@ func (r *marathonClient) GroupBy(name string, opts *GetGroupOpts) (*Group, error // HasGroup checks if the group exists in marathon // name: the identifier for the group func (r *marathonClient) HasGroup(name string) (bool, error) { - uri := fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)) - err := r.apiCall("GET", uri, "", nil) + path := fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)) + err := r.apiCall("GET", path, "", nil) if err != nil { if apiErr, ok := err.(*APIError); ok && apiErr.ErrCode == ErrCodeNotFound { return false, nil @@ -208,11 +208,9 @@ func (r *marathonClient) WaitOnGroup(name string, timeout time.Duration) error { // force: used to force the delete operation in case of blocked deployment func (r *marathonClient) DeleteGroup(name string, force bool) (*DeploymentID, error) { version := new(DeploymentID) - uri := fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)) - if force { - uri = uri + "?force=true" - } - if err := r.apiDelete(uri, nil, version); err != nil { + path := fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)) + path = buildPathWithForceParam(path, force) + if err := r.apiDelete(path, nil, version); err != nil { return nil, err } @@ -225,11 +223,9 @@ func (r *marathonClient) DeleteGroup(name string, force bool) (*DeploymentID, er // force: used to force the update operation in case of blocked deployment func (r *marathonClient) UpdateGroup(name string, group *Group, force bool) (*DeploymentID, error) { deploymentID := new(DeploymentID) - uri := fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)) - if force { - uri = uri + "?force=true" - } - if err := r.apiPut(uri, group, deploymentID); err != nil { + path := fmt.Sprintf("%s/%s", marathonAPIGroups, trimRootPath(name)) + path = buildPathWithForceParam(path, force) + if err := r.apiPut(path, group, deploymentID); err != nil { return nil, err } diff --git a/vendor/github.com/gambol99/go-marathon/queue.go b/vendor/github.com/gambol99/go-marathon/queue.go index dfd8c7e92..436489377 100644 --- a/vendor/github.com/gambol99/go-marathon/queue.go +++ b/vendor/github.com/gambol99/go-marathon/queue.go @@ -51,8 +51,8 @@ func (r *marathonClient) Queue() (*Queue, error) { // DeleteQueueDelay resets task launch delay of the specific application // appID: the ID of the application func (r *marathonClient) DeleteQueueDelay(appID string) error { - uri := fmt.Sprintf("%s/%s/delay", marathonAPIQueue, trimRootPath(appID)) - err := r.apiDelete(uri, nil, nil) + path := fmt.Sprintf("%s/%s/delay", marathonAPIQueue, trimRootPath(appID)) + err := r.apiDelete(path, nil, nil) if err != nil { return err } diff --git a/vendor/github.com/gambol99/go-marathon/subscription.go b/vendor/github.com/gambol99/go-marathon/subscription.go index f1c7e25d6..7a625a973 100644 --- a/vendor/github.com/gambol99/go-marathon/subscription.go +++ b/vendor/github.com/gambol99/go-marathon/subscription.go @@ -201,8 +201,8 @@ func (r *marathonClient) registerSSESubscription() error { // Subscribe adds a URL to Marathon's callback facility // callback : the URL you wish to subscribe func (r *marathonClient) Subscribe(callback string) error { - uri := fmt.Sprintf("%s?callbackUrl=%s", marathonAPISubscription, callback) - return r.apiPost(uri, "", nil) + path := fmt.Sprintf("%s?callbackUrl=%s", marathonAPISubscription, callback) + return r.apiPost(path, "", nil) } diff --git a/vendor/github.com/gambol99/go-marathon/task.go b/vendor/github.com/gambol99/go-marathon/task.go index 336ed37f2..cb7afed35 100644 --- a/vendor/github.com/gambol99/go-marathon/task.go +++ b/vendor/github.com/gambol99/go-marathon/task.go @@ -79,13 +79,13 @@ func (r *Task) HasHealthCheckResults() bool { // AllTasks lists tasks of all applications. // opts: AllTasksOpts request payload func (r *marathonClient) AllTasks(opts *AllTasksOpts) (*Tasks, error) { - u, err := addOptions(marathonAPITasks, opts) + path, err := addOptions(marathonAPITasks, opts) if err != nil { return nil, err } tasks := new(Tasks) - if err := r.apiGet(u, nil, tasks); err != nil { + if err := r.apiGet(path, nil, tasks); err != nil { return nil, err } @@ -107,14 +107,14 @@ func (r *marathonClient) Tasks(id string) (*Tasks, error) { // id: the id of the application // opts: KillApplicationTasksOpts request payload func (r *marathonClient) KillApplicationTasks(id string, opts *KillApplicationTasksOpts) (*Tasks, error) { - u := fmt.Sprintf("%s/%s/tasks", marathonAPIApps, trimRootPath(id)) - u, err := addOptions(u, opts) + path := fmt.Sprintf("%s/%s/tasks", marathonAPIApps, trimRootPath(id)) + path, err := addOptions(path, opts) if err != nil { return nil, err } tasks := new(Tasks) - if err := r.apiDelete(u, nil, tasks); err != nil { + if err := r.apiDelete(path, nil, tasks); err != nil { return nil, err } @@ -129,8 +129,8 @@ func (r *marathonClient) KillTask(taskID string, opts *KillTaskOpts) (*Task, err appName = strings.Replace(appName, "_", "/", -1) taskID = strings.Replace(taskID, "/", "_", -1) - u := fmt.Sprintf("%s/%s/tasks/%s", marathonAPIApps, appName, taskID) - u, err := addOptions(u, opts) + path := fmt.Sprintf("%s/%s/tasks/%s", marathonAPIApps, appName, taskID) + path, err := addOptions(path, opts) if err != nil { return nil, err } @@ -139,7 +139,7 @@ func (r *marathonClient) KillTask(taskID string, opts *KillTaskOpts) (*Task, err Task Task `json:"task"` }) - if err := r.apiDelete(u, nil, wrappedTask); err != nil { + if err := r.apiDelete(path, nil, wrappedTask); err != nil { return nil, err } @@ -150,8 +150,8 @@ func (r *marathonClient) KillTask(taskID string, opts *KillTaskOpts) (*Task, err // tasks: the array of task ids // opts: KillTaskOpts request payload func (r *marathonClient) KillTasks(tasks []string, opts *KillTaskOpts) error { - u := fmt.Sprintf("%s/delete", marathonAPITasks) - u, err := addOptions(u, opts) + path := fmt.Sprintf("%s/delete", marathonAPITasks) + path, err := addOptions(path, opts) if err != nil { return nil } @@ -161,7 +161,7 @@ func (r *marathonClient) KillTasks(tasks []string, opts *KillTaskOpts) error { } post.IDs = tasks - return r.apiPost(u, &post, nil) + return r.apiPost(path, &post, nil) } // TaskEndpoints gets the endpoints i.e. HOST_IP:DYNAMIC_PORT for a specific application service diff --git a/vendor/github.com/gambol99/go-marathon/unreachable_strategy.go b/vendor/github.com/gambol99/go-marathon/unreachable_strategy.go new file mode 100644 index 000000000..a15f7afe6 --- /dev/null +++ b/vendor/github.com/gambol99/go-marathon/unreachable_strategy.go @@ -0,0 +1,35 @@ +/* +Copyright 2017 Rohith All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package marathon + +// UnreachableStrategy is the unreachable strategy applied to an application. +type UnreachableStrategy struct { + InactiveAfterSeconds *float64 `json:"inactiveAfterSeconds,omitempty"` + ExpungeAfterSeconds *float64 `json:"expungeAfterSeconds,omitempty"` +} + +// SetInactiveAfterSeconds sets the period after which instance will be marked as inactive. +func (us UnreachableStrategy) SetInactiveAfterSeconds(cap float64) UnreachableStrategy { + us.InactiveAfterSeconds = &cap + return us +} + +// SetExpungeAfterSeconds sets the period after which instance will be expunged. +func (us UnreachableStrategy) SetExpungeAfterSeconds(cap float64) UnreachableStrategy { + us.ExpungeAfterSeconds = &cap + return us +} diff --git a/vendor/github.com/gambol99/go-marathon/update_strategy.go b/vendor/github.com/gambol99/go-marathon/upgrade_strategy.go similarity index 100% rename from vendor/github.com/gambol99/go-marathon/update_strategy.go rename to vendor/github.com/gambol99/go-marathon/upgrade_strategy.go