Adding compatibility for marathon 1.5
This commit is contained in:
parent
461ebf6d88
commit
04d8b5d483
35 changed files with 2257 additions and 63 deletions
2
Gopkg.lock
generated
2
Gopkg.lock
generated
|
@ -540,7 +540,7 @@
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/gambol99/go-marathon"
|
name = "github.com/gambol99/go-marathon"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "03b46169666c53b9cc953b875ac5714e5103e064"
|
revision = "99a156b96fb2f9dbe6465affa51bbdccdd37174d"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/ghodss/yaml"
|
name = "github.com/ghodss/yaml"
|
||||||
|
|
|
@ -55,6 +55,7 @@ func init() {
|
||||||
check.Suite(&HTTPSSuite{})
|
check.Suite(&HTTPSSuite{})
|
||||||
check.Suite(&LogRotationSuite{})
|
check.Suite(&LogRotationSuite{})
|
||||||
check.Suite(&MarathonSuite{})
|
check.Suite(&MarathonSuite{})
|
||||||
|
check.Suite(&MarathonSuite15{})
|
||||||
check.Suite(&MesosSuite{})
|
check.Suite(&MesosSuite{})
|
||||||
check.Suite(&RateLimitSuite{})
|
check.Suite(&RateLimitSuite{})
|
||||||
check.Suite(&RetrySuite{})
|
check.Suite(&RetrySuite{})
|
||||||
|
|
134
integration/marathon15_test.go
Normal file
134
integration/marathon15_test.go
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
package integration
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/traefik/integration/try"
|
||||||
|
"github.com/containous/traefik/provider/label"
|
||||||
|
"github.com/gambol99/go-marathon"
|
||||||
|
"github.com/go-check/check"
|
||||||
|
checker "github.com/vdemeester/shakers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Marathon test suites (using libcompose)
|
||||||
|
type MarathonSuite15 struct {
|
||||||
|
BaseSuite
|
||||||
|
marathonURL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MarathonSuite15) SetUpSuite(c *check.C) {
|
||||||
|
s.createComposeProject(c, "marathon15")
|
||||||
|
s.composeProject.Start(c)
|
||||||
|
|
||||||
|
marathonIPAddr := s.composeProject.Container(c, containerNameMarathon).NetworkSettings.IPAddress
|
||||||
|
c.Assert(marathonIPAddr, checker.Not(checker.HasLen), 0)
|
||||||
|
s.marathonURL = "http://" + marathonIPAddr + ":8080"
|
||||||
|
|
||||||
|
// Wait for Marathon readiness prior to creating the client so that we
|
||||||
|
// don't run into the "all cluster members down" state right from the
|
||||||
|
// start.
|
||||||
|
err := try.GetRequest(s.marathonURL+"/v2/leader", 1*time.Minute, try.StatusCodeIs(http.StatusOK))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Add entry for Mesos slave container IP address in the hosts file so
|
||||||
|
// that Traefik can properly forward traffic.
|
||||||
|
// This is necessary as long as we are still using the docker-compose v1
|
||||||
|
// spec. Once we switch to v2 or higher, we can have both the test/builder
|
||||||
|
// container and the Mesos slave container join the same custom network and
|
||||||
|
// enjoy DNS-discoverable container host names.
|
||||||
|
mesosSlaveIPAddr := s.composeProject.Container(c, containerNameMesosSlave).NetworkSettings.IPAddress
|
||||||
|
c.Assert(mesosSlaveIPAddr, checker.Not(checker.HasLen), 0)
|
||||||
|
err = s.extendDockerHostsFile(containerNameMesosSlave, mesosSlaveIPAddr)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// extendDockerHostsFile extends the hosts file (/etc/hosts) by the given
|
||||||
|
// host/IP address mapping if we are running inside a container.
|
||||||
|
func (s *MarathonSuite15) extendDockerHostsFile(host, ipAddr string) error {
|
||||||
|
const hostsFile = "/etc/hosts"
|
||||||
|
|
||||||
|
// Determine if the run inside a container. The most reliable way to
|
||||||
|
// do this is to inject an indicator, which we do in terms of an
|
||||||
|
// environment variable.
|
||||||
|
// (See also https://groups.google.com/d/topic/docker-user/JOGE7AnJ3Gw/discussion.)
|
||||||
|
if os.Getenv("CONTAINER") == "DOCKER" {
|
||||||
|
// We are running inside a container -- extend the hosts file.
|
||||||
|
file, err := os.OpenFile(hostsFile, os.O_APPEND|os.O_WRONLY, 0600)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if _, err = file.WriteString(fmt.Sprintf("%s\t%s\n", ipAddr, host)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MarathonSuite15) TestConfigurationUpdate(c *check.C) {
|
||||||
|
// Start Traefik.
|
||||||
|
file := s.adaptFile(c, "fixtures/marathon/simple.toml", struct {
|
||||||
|
MarathonURL string
|
||||||
|
}{s.marathonURL})
|
||||||
|
defer os.Remove(file)
|
||||||
|
cmd, display := s.traefikCmd(withConfigFile(file))
|
||||||
|
defer display(c)
|
||||||
|
err := cmd.Start()
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
defer cmd.Process.Kill()
|
||||||
|
|
||||||
|
// Wait for Traefik to turn ready.
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8000/", 2*time.Second, try.StatusCodeIs(http.StatusNotFound))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Prepare Marathon client.
|
||||||
|
config := marathon.NewDefaultConfig()
|
||||||
|
config.URL = s.marathonURL
|
||||||
|
client, err := marathon.NewClient(config)
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Create test application to be deployed.
|
||||||
|
app := marathon.NewDockerApplication().
|
||||||
|
Name("/whoami").
|
||||||
|
CPU(0.1).
|
||||||
|
Memory(32).
|
||||||
|
EmptyNetworks().
|
||||||
|
AddLabel(label.TraefikFrontendRule, "PathPrefix:/service")
|
||||||
|
app.Container.
|
||||||
|
Expose(80).
|
||||||
|
Docker.
|
||||||
|
Container("emilevauge/whoami")
|
||||||
|
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
|
||||||
|
|
||||||
|
// Deploy the test application.
|
||||||
|
deployApplication(c, client, app)
|
||||||
|
|
||||||
|
// Query application via Traefik.
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8000/service", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
|
||||||
|
// Create test application with services to be deployed.
|
||||||
|
app = marathon.NewDockerApplication().
|
||||||
|
Name("/whoami").
|
||||||
|
CPU(0.1).
|
||||||
|
Memory(32).
|
||||||
|
EmptyNetworks().
|
||||||
|
AddLabel(label.GetServiceLabel(label.TraefikFrontendRule, "app"), "PathPrefix:/app")
|
||||||
|
app.Container.
|
||||||
|
Expose(80).
|
||||||
|
Docker.
|
||||||
|
Container("emilevauge/whoami")
|
||||||
|
*app.Networks = append(*app.Networks, *marathon.NewBridgePodNetwork())
|
||||||
|
|
||||||
|
// Deploy the test application.
|
||||||
|
deployApplication(c, client, app)
|
||||||
|
|
||||||
|
// Query application via Traefik.
|
||||||
|
err = try.GetRequest("http://127.0.0.1:8000/app", 30*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||||
|
c.Assert(err, checker.IsNil)
|
||||||
|
}
|
55
integration/resources/compose/marathon15.yml
Normal file
55
integration/resources/compose/marathon15.yml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
zookeeper:
|
||||||
|
image: zookeeper:3.4.10
|
||||||
|
|
||||||
|
mesos-master:
|
||||||
|
links:
|
||||||
|
- zookeeper
|
||||||
|
image: mesosphere/mesos-master:1.4.1
|
||||||
|
# Uncomment published ports for interactive debugging.
|
||||||
|
# ports:
|
||||||
|
# - "5050:5050"
|
||||||
|
environment:
|
||||||
|
- MESOS_HOSTNAME=mesos-master
|
||||||
|
- MESOS_CLUSTER=local
|
||||||
|
- MESOS_REGISTRY=in_memory
|
||||||
|
- MESOS_LOG_DIR=/var/log
|
||||||
|
- MESOS_WORK_DIR=/var/lib/mesos
|
||||||
|
- MESOS_ZK=zk://zookeeper:2181/mesos
|
||||||
|
|
||||||
|
mesos-slave:
|
||||||
|
links:
|
||||||
|
- zookeeper
|
||||||
|
- mesos-master
|
||||||
|
image: mesosphere/mesos-slave-dind:0.4.0_mesos-1.4.1_docker-17.05.0_ubuntu-16.04.3
|
||||||
|
privileged: true
|
||||||
|
# Uncomment published ports for interactive debugging.
|
||||||
|
# ports:
|
||||||
|
# - "5051:5051"
|
||||||
|
environment:
|
||||||
|
- MESOS_HOSTNAME=mesos-slave
|
||||||
|
- MESOS_CONTAINERIZERS=docker,mesos
|
||||||
|
- MESOS_ISOLATOR=cgroups/cpu,cgroups/mem
|
||||||
|
- MESOS_LOG_DIR=/var/log
|
||||||
|
- MESOS_MASTER=zk://zookeeper:2181/mesos
|
||||||
|
- MESOS_PORT=5051
|
||||||
|
- MESOS_WORK_DIR=/var/lib/mesos
|
||||||
|
- MESOS_EXECUTOR_REGISTRATION_TIMEOUT=5mins
|
||||||
|
- MESOS_EXECUTOR_SHUTDOWN_GRACE_PERIOD=90secs
|
||||||
|
- MESOS_DOCKER_STOP_TIMEOUT=60secs
|
||||||
|
- MESOS_RESOURCES=cpus:2;mem:2048;disk:20480;ports(*):[12000-12999]
|
||||||
|
- MESOS_SYSTEMD_ENABLE_SUPPORT=false
|
||||||
|
|
||||||
|
marathon:
|
||||||
|
links:
|
||||||
|
- zookeeper
|
||||||
|
- mesos-master
|
||||||
|
- mesos-slave
|
||||||
|
image: mesosphere/marathon:v1.5.9
|
||||||
|
# Uncomment published ports for interactive debugging.
|
||||||
|
# ports:
|
||||||
|
# - "8080:8080"
|
||||||
|
extra_hosts:
|
||||||
|
- "mesos-slave:172.17.0.1"
|
||||||
|
environment:
|
||||||
|
- MARATHON_ZK=zk://zookeeper:2181/marathon
|
||||||
|
- MARATHON_MASTER=zk://zookeeper:2181/mesos
|
|
@ -83,6 +83,24 @@ func portDefinition(port int) func(*marathon.Application) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func bridgeNetwork() func(*marathon.Application) {
|
||||||
|
return func(app *marathon.Application) {
|
||||||
|
app.SetNetwork("bridge", marathon.BridgeNetworkMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func containerNetwork() func(*marathon.Application) {
|
||||||
|
return func(app *marathon.Application) {
|
||||||
|
app.SetNetwork("cni", marathon.ContainerNetworkMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hostNetwork() func(*marathon.Application) {
|
||||||
|
return func(app *marathon.Application) {
|
||||||
|
app.SetNetwork("host", marathon.HostNetworkMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ipAddrPerTask(port int) func(*marathon.Application) {
|
func ipAddrPerTask(port int) func(*marathon.Application) {
|
||||||
return func(app *marathon.Application) {
|
return func(app *marathon.Application) {
|
||||||
p := marathon.Port{
|
p := marathon.Port{
|
||||||
|
|
|
@ -347,7 +347,16 @@ func (p *Provider) getServer(app appData, task marathon.Task) (string, *types.Se
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provider) getServerHost(task marathon.Task, app appData) (string, error) {
|
func (p *Provider) getServerHost(task marathon.Task, app appData) (string, error) {
|
||||||
if app.IPAddressPerTask == nil || p.ForceTaskHostname {
|
networks := app.Networks
|
||||||
|
var hostFlag bool
|
||||||
|
|
||||||
|
if networks == nil {
|
||||||
|
hostFlag = app.IPAddressPerTask == nil
|
||||||
|
} else {
|
||||||
|
hostFlag = (*networks)[0].Mode != marathon.ContainerNetworkMode
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostFlag || p.ForceTaskHostname {
|
||||||
if len(task.Host) == 0 {
|
if len(task.Host) == 0 {
|
||||||
return "", fmt.Errorf("host is undefined for task %q app %q", task.ID, app.ID)
|
return "", fmt.Errorf("host is undefined for task %q app %q", task.ID, app.ID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1289,7 +1289,30 @@ func TestGetServers(t *testing.T) {
|
||||||
expected: nil,
|
expected: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "with 3 tasks",
|
desc: "with 3 tasks and hosts set",
|
||||||
|
application: application(
|
||||||
|
withTasks(
|
||||||
|
task(ipAddresses("1.1.1.1"), host("2.2.2.2"), withTaskID("A"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.2"), host("2.2.2.2"), withTaskID("B"), taskPorts(81)),
|
||||||
|
task(ipAddresses("1.1.1.3"), host("2.2.2.2"), withTaskID("C"), taskPorts(82))),
|
||||||
|
),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server-A": {
|
||||||
|
URL: "http://2.2.2.2:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-B": {
|
||||||
|
URL: "http://2.2.2.2:81",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-C": {
|
||||||
|
URL: "http://2.2.2.2:82",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "with 3 tasks and ipAddrPerTask set",
|
||||||
application: application(
|
application: application(
|
||||||
ipAddrPerTask(80),
|
ipAddrPerTask(80),
|
||||||
withTasks(
|
withTasks(
|
||||||
|
@ -1312,13 +1335,60 @@ func TestGetServers(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "with 3 tasks and bridge network",
|
||||||
|
application: application(
|
||||||
|
bridgeNetwork(),
|
||||||
|
withTasks(
|
||||||
|
task(ipAddresses("1.1.1.1"), host("2.2.2.2"), withTaskID("A"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.2"), host("2.2.2.2"), withTaskID("B"), taskPorts(81)),
|
||||||
|
task(ipAddresses("1.1.1.3"), host("2.2.2.2"), withTaskID("C"), taskPorts(82))),
|
||||||
|
),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server-A": {
|
||||||
|
URL: "http://2.2.2.2:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-B": {
|
||||||
|
URL: "http://2.2.2.2:81",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-C": {
|
||||||
|
URL: "http://2.2.2.2:82",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "with 3 tasks and cni set",
|
||||||
|
application: application(
|
||||||
|
containerNetwork(),
|
||||||
|
withTasks(
|
||||||
|
task(ipAddresses("1.1.1.1"), withTaskID("A"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.2"), withTaskID("B"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.3"), withTaskID("C"), taskPorts(80))),
|
||||||
|
),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server-A": {
|
||||||
|
URL: "http://1.1.1.1:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-B": {
|
||||||
|
URL: "http://1.1.1.2:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-C": {
|
||||||
|
URL: "http://1.1.1.3:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &Provider{}
|
p := &Provider{}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
test := test
|
test := test
|
||||||
if test.desc == "should return nil when all hosts are empty" {
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -1327,5 +1397,4 @@ func TestGetServers(t *testing.T) {
|
||||||
assert.Equal(t, test.expected, actual)
|
assert.Equal(t, test.expected, actual)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,11 +147,21 @@ func (p *Provider) getFrontendRuleV1(application marathon.Application, serviceNa
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
func (p *Provider) getBackendServerV1(task marathon.Task, application marathon.Application) string {
|
func (p *Provider) getBackendServerV1(task marathon.Task, application marathon.Application) string {
|
||||||
if application.IPAddressPerTask == nil || p.ForceTaskHostname {
|
networks := application.Networks
|
||||||
|
var hostFlag bool
|
||||||
|
|
||||||
|
if networks == nil {
|
||||||
|
hostFlag = application.IPAddressPerTask == nil
|
||||||
|
} else {
|
||||||
|
hostFlag = (*networks)[0].Mode != marathon.ContainerNetworkMode
|
||||||
|
}
|
||||||
|
|
||||||
|
if hostFlag || p.ForceTaskHostname {
|
||||||
return task.Host
|
return task.Host
|
||||||
}
|
}
|
||||||
|
|
||||||
numTaskIPAddresses := len(task.IPAddresses)
|
numTaskIPAddresses := len(task.IPAddresses)
|
||||||
|
|
||||||
switch numTaskIPAddresses {
|
switch numTaskIPAddresses {
|
||||||
case 0:
|
case 0:
|
||||||
log.Errorf("Missing IP address for Marathon application %s on task %s", application.ID, task.ID)
|
log.Errorf("Missing IP address for Marathon application %s on task %s", application.ID, task.ID)
|
||||||
|
|
|
@ -784,7 +784,30 @@ func TestGetServersV1(t *testing.T) {
|
||||||
expected: nil,
|
expected: nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desc: "with 3 tasks",
|
desc: "with 3 tasks and hosts set",
|
||||||
|
application: application(
|
||||||
|
withTasks(
|
||||||
|
task(ipAddresses("1.1.1.1"), host("2.2.2.2"), withTaskID("A"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.2"), host("2.2.2.2"), withTaskID("B"), taskPorts(81)),
|
||||||
|
task(ipAddresses("1.1.1.3"), host("2.2.2.2"), withTaskID("C"), taskPorts(82))),
|
||||||
|
),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server-A": {
|
||||||
|
URL: "http://2.2.2.2:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-B": {
|
||||||
|
URL: "http://2.2.2.2:81",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-C": {
|
||||||
|
URL: "http://2.2.2.2:82",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "with 3 tasks and ipAddrPerTask set",
|
||||||
application: application(
|
application: application(
|
||||||
ipAddrPerTask(80),
|
ipAddrPerTask(80),
|
||||||
withTasks(
|
withTasks(
|
||||||
|
@ -807,13 +830,60 @@ func TestGetServersV1(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "with 3 tasks and bridge network",
|
||||||
|
application: application(
|
||||||
|
bridgeNetwork(),
|
||||||
|
withTasks(
|
||||||
|
task(ipAddresses("1.1.1.1"), host("2.2.2.2"), withTaskID("A"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.2"), host("2.2.2.2"), withTaskID("B"), taskPorts(81)),
|
||||||
|
task(ipAddresses("1.1.1.3"), host("2.2.2.2"), withTaskID("C"), taskPorts(82))),
|
||||||
|
),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server-A": {
|
||||||
|
URL: "http://2.2.2.2:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-B": {
|
||||||
|
URL: "http://2.2.2.2:81",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-C": {
|
||||||
|
URL: "http://2.2.2.2:82",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "with 3 tasks and cni set",
|
||||||
|
application: application(
|
||||||
|
containerNetwork(),
|
||||||
|
withTasks(
|
||||||
|
task(ipAddresses("1.1.1.1"), withTaskID("A"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.2"), withTaskID("B"), taskPorts(80)),
|
||||||
|
task(ipAddresses("1.1.1.3"), withTaskID("C"), taskPorts(80))),
|
||||||
|
),
|
||||||
|
expected: map[string]types.Server{
|
||||||
|
"server-A": {
|
||||||
|
URL: "http://1.1.1.1:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-B": {
|
||||||
|
URL: "http://1.1.1.2:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
"server-C": {
|
||||||
|
URL: "http://1.1.1.3:80",
|
||||||
|
Weight: label.DefaultWeight,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
p := &Provider{}
|
p := &Provider{}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
test := test
|
test := test
|
||||||
if test.desc == "should return nil when all hosts are empty" {
|
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -822,5 +892,4 @@ func TestGetServersV1(t *testing.T) {
|
||||||
assert.Equal(t, test.expected, actual)
|
assert.Equal(t, test.expected, actual)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Package mocks Code generated by mockery v1.0.0
|
// Package mocks Code generated by mockery v1.0.0. DO NOT EDIT.
|
||||||
// mockery -recursive -dir=vendor/github.com/gambol99/ -name=Marathon -output=provider/marathon/mocks
|
// mockery -recursive -dir=vendor/github.com/gambol99/ -name=Marathon -output=provider/marathon/mocks
|
||||||
package mocks
|
package mocks
|
||||||
|
|
||||||
|
@ -278,6 +278,29 @@ func (_m *Marathon) CreateGroup(group *marathon.Group) error {
|
||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreatePod provides a mock function with given fields: pod
|
||||||
|
func (_m *Marathon) CreatePod(pod *marathon.Pod) (*marathon.Pod, error) {
|
||||||
|
ret := _m.Called(pod)
|
||||||
|
|
||||||
|
var r0 *marathon.Pod
|
||||||
|
if rf, ok := ret.Get(0).(func(*marathon.Pod) *marathon.Pod); ok {
|
||||||
|
r0 = rf(pod)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*marathon.Pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*marathon.Pod) error); ok {
|
||||||
|
r1 = rf(pod)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteApplication provides a mock function with given fields: name, force
|
// DeleteApplication provides a mock function with given fields: name, force
|
||||||
func (_m *Marathon) DeleteApplication(name string, force bool) (*marathon.DeploymentID, error) {
|
func (_m *Marathon) DeleteApplication(name string, force bool) (*marathon.DeploymentID, error) {
|
||||||
ret := _m.Called(name, force)
|
ret := _m.Called(name, force)
|
||||||
|
@ -347,6 +370,75 @@ func (_m *Marathon) DeleteGroup(name string, force bool) (*marathon.DeploymentID
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeletePod provides a mock function with given fields: name, force
|
||||||
|
func (_m *Marathon) DeletePod(name string, force bool) (*marathon.DeploymentID, error) {
|
||||||
|
ret := _m.Called(name, force)
|
||||||
|
|
||||||
|
var r0 *marathon.DeploymentID
|
||||||
|
if rf, ok := ret.Get(0).(func(string, bool) *marathon.DeploymentID); ok {
|
||||||
|
r0 = rf(name, force)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*marathon.DeploymentID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string, bool) error); ok {
|
||||||
|
r1 = rf(name, force)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePodInstance provides a mock function with given fields: name, instance
|
||||||
|
func (_m *Marathon) DeletePodInstance(name string, instance string) (*marathon.PodInstance, error) {
|
||||||
|
ret := _m.Called(name, instance)
|
||||||
|
|
||||||
|
var r0 *marathon.PodInstance
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string) *marathon.PodInstance); ok {
|
||||||
|
r0 = rf(name, instance)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*marathon.PodInstance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
||||||
|
r1 = rf(name, instance)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePodInstances provides a mock function with given fields: name, instances
|
||||||
|
func (_m *Marathon) DeletePodInstances(name string, instances []string) ([]*marathon.PodInstance, error) {
|
||||||
|
ret := _m.Called(name, instances)
|
||||||
|
|
||||||
|
var r0 []*marathon.PodInstance
|
||||||
|
if rf, ok := ret.Get(0).(func(string, []string) []*marathon.PodInstance); ok {
|
||||||
|
r0 = rf(name, instances)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*marathon.PodInstance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string, []string) error); ok {
|
||||||
|
r1 = rf(name, instances)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteQueueDelay provides a mock function with given fields: appID
|
// DeleteQueueDelay provides a mock function with given fields: appID
|
||||||
func (_m *Marathon) DeleteQueueDelay(appID string) error {
|
func (_m *Marathon) DeleteQueueDelay(appID string) error {
|
||||||
ret := _m.Called(appID)
|
ret := _m.Called(appID)
|
||||||
|
@ -701,6 +793,158 @@ func (_m *Marathon) Ping() (bool, error) {
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pod provides a mock function with given fields: name
|
||||||
|
func (_m *Marathon) Pod(name string) (*marathon.Pod, error) {
|
||||||
|
ret := _m.Called(name)
|
||||||
|
|
||||||
|
var r0 *marathon.Pod
|
||||||
|
if rf, ok := ret.Get(0).(func(string) *marathon.Pod); ok {
|
||||||
|
r0 = rf(name)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*marathon.Pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||||
|
r1 = rf(name)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodByVersion provides a mock function with given fields: name, version
|
||||||
|
func (_m *Marathon) PodByVersion(name string, version string) (*marathon.Pod, error) {
|
||||||
|
ret := _m.Called(name, version)
|
||||||
|
|
||||||
|
var r0 *marathon.Pod
|
||||||
|
if rf, ok := ret.Get(0).(func(string, string) *marathon.Pod); ok {
|
||||||
|
r0 = rf(name, version)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*marathon.Pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
||||||
|
r1 = rf(name, version)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodIsRunning provides a mock function with given fields: name
|
||||||
|
func (_m *Marathon) PodIsRunning(name string) bool {
|
||||||
|
ret := _m.Called(name)
|
||||||
|
|
||||||
|
var r0 bool
|
||||||
|
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||||
|
r0 = rf(name)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodStatus provides a mock function with given fields: name
|
||||||
|
func (_m *Marathon) PodStatus(name string) (*marathon.PodStatus, error) {
|
||||||
|
ret := _m.Called(name)
|
||||||
|
|
||||||
|
var r0 *marathon.PodStatus
|
||||||
|
if rf, ok := ret.Get(0).(func(string) *marathon.PodStatus); ok {
|
||||||
|
r0 = rf(name)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*marathon.PodStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||||
|
r1 = rf(name)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodStatuses provides a mock function with given fields:
|
||||||
|
func (_m *Marathon) PodStatuses() ([]*marathon.PodStatus, error) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 []*marathon.PodStatus
|
||||||
|
if rf, ok := ret.Get(0).(func() []*marathon.PodStatus); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]*marathon.PodStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func() error); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodVersions provides a mock function with given fields: name
|
||||||
|
func (_m *Marathon) PodVersions(name string) ([]string, error) {
|
||||||
|
ret := _m.Called(name)
|
||||||
|
|
||||||
|
var r0 []string
|
||||||
|
if rf, ok := ret.Get(0).(func(string) []string); ok {
|
||||||
|
r0 = rf(name)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||||
|
r1 = rf(name)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pods provides a mock function with given fields:
|
||||||
|
func (_m *Marathon) Pods() ([]marathon.Pod, error) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 []marathon.Pod
|
||||||
|
if rf, ok := ret.Get(0).(func() []marathon.Pod); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).([]marathon.Pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func() error); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// Queue provides a mock function with given fields:
|
// Queue provides a mock function with given fields:
|
||||||
func (_m *Marathon) Queue() (*marathon.Queue, error) {
|
func (_m *Marathon) Queue() (*marathon.Queue, error) {
|
||||||
ret := _m.Called()
|
ret := _m.Called()
|
||||||
|
@ -835,6 +1079,27 @@ func (_m *Marathon) Subscriptions() (*marathon.Subscriptions, error) {
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportsPods provides a mock function with given fields:
|
||||||
|
func (_m *Marathon) SupportsPods() (bool, error) {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 bool
|
||||||
|
if rf, ok := ret.Get(0).(func() bool); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func() error); ok {
|
||||||
|
r1 = rf()
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// TaskEndpoints provides a mock function with given fields: name, port, healthCheck
|
// TaskEndpoints provides a mock function with given fields: name, port, healthCheck
|
||||||
func (_m *Marathon) TaskEndpoints(name string, port int, healthCheck bool) ([]string, error) {
|
func (_m *Marathon) TaskEndpoints(name string, port int, healthCheck bool) ([]string, error) {
|
||||||
ret := _m.Called(name, port, healthCheck)
|
ret := _m.Called(name, port, healthCheck)
|
||||||
|
@ -941,6 +1206,29 @@ func (_m *Marathon) UpdateGroup(id string, group *marathon.Group, force bool) (*
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdatePod provides a mock function with given fields: pod, force
|
||||||
|
func (_m *Marathon) UpdatePod(pod *marathon.Pod, force bool) (*marathon.Pod, error) {
|
||||||
|
ret := _m.Called(pod, force)
|
||||||
|
|
||||||
|
var r0 *marathon.Pod
|
||||||
|
if rf, ok := ret.Get(0).(func(*marathon.Pod, bool) *marathon.Pod); ok {
|
||||||
|
r0 = rf(pod, force)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*marathon.Pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(*marathon.Pod, bool) error); ok {
|
||||||
|
r1 = rf(pod, force)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// WaitOnApplication provides a mock function with given fields: name, timeout
|
// WaitOnApplication provides a mock function with given fields: name, timeout
|
||||||
func (_m *Marathon) WaitOnApplication(name string, timeout time.Duration) error {
|
func (_m *Marathon) WaitOnApplication(name string, timeout time.Duration) error {
|
||||||
ret := _m.Called(name, timeout)
|
ret := _m.Called(name, timeout)
|
||||||
|
@ -982,3 +1270,17 @@ func (_m *Marathon) WaitOnGroup(name string, timeout time.Duration) error {
|
||||||
|
|
||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitOnPod provides a mock function with given fields: name, timeout
|
||||||
|
func (_m *Marathon) WaitOnPod(name string, timeout time.Duration) error {
|
||||||
|
ret := _m.Called(name, timeout)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(string, time.Duration) error); ok {
|
||||||
|
r0 = rf(name, timeout)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
46
vendor/github.com/gambol99/go-marathon/application.go
generated
vendored
46
vendor/github.com/gambol99/go-marathon/application.go
generated
vendored
|
@ -64,6 +64,8 @@ type Application struct {
|
||||||
CPUs float64 `json:"cpus,omitempty"`
|
CPUs float64 `json:"cpus,omitempty"`
|
||||||
GPUs *float64 `json:"gpus,omitempty"`
|
GPUs *float64 `json:"gpus,omitempty"`
|
||||||
Disk *float64 `json:"disk,omitempty"`
|
Disk *float64 `json:"disk,omitempty"`
|
||||||
|
Networks *[]PodNetwork `json:"networks,omitempty"`
|
||||||
|
|
||||||
// Contains non-secret environment variables. Secrets environment variables are part of the Secrets map.
|
// Contains non-secret environment variables. Secrets environment variables are part of the Secrets map.
|
||||||
Env *map[string]string `json:"-"`
|
Env *map[string]string `json:"-"`
|
||||||
Executor *string `json:"executor,omitempty"`
|
Executor *string `json:"executor,omitempty"`
|
||||||
|
@ -494,9 +496,12 @@ func (r *Application) CheckHTTP(path string, port, interval int) (*Application,
|
||||||
}
|
}
|
||||||
// step: get the port index
|
// step: get the port index
|
||||||
portIndex, err := r.Container.Docker.ServicePortIndex(port)
|
portIndex, err := r.Container.Docker.ServicePortIndex(port)
|
||||||
|
if err != nil {
|
||||||
|
portIndex, err = r.Container.ServicePortIndex(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
health := NewDefaultHealthCheck()
|
health := NewDefaultHealthCheck()
|
||||||
health.IntervalSeconds = interval
|
health.IntervalSeconds = interval
|
||||||
*health.Path = path
|
*health.Path = path
|
||||||
|
@ -517,9 +522,12 @@ func (r *Application) CheckTCP(port, interval int) (*Application, error) {
|
||||||
}
|
}
|
||||||
// step: get the port index
|
// step: get the port index
|
||||||
portIndex, err := r.Container.Docker.ServicePortIndex(port)
|
portIndex, err := r.Container.Docker.ServicePortIndex(port)
|
||||||
|
if err != nil {
|
||||||
|
portIndex, err = r.Container.ServicePortIndex(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
health := NewDefaultHealthCheck()
|
health := NewDefaultHealthCheck()
|
||||||
health.Protocol = "TCP"
|
health.Protocol = "TCP"
|
||||||
health.IntervalSeconds = interval
|
health.IntervalSeconds = interval
|
||||||
|
@ -810,24 +818,7 @@ func (r *marathonClient) CreateApplication(application *Application) (*Applicati
|
||||||
// name: the id of the application
|
// name: the id of the application
|
||||||
// timeout: a duration of time to wait for an application to deploy
|
// timeout: a duration of time to wait for an application to deploy
|
||||||
func (r *marathonClient) WaitOnApplication(name string, timeout time.Duration) error {
|
func (r *marathonClient) WaitOnApplication(name string, timeout time.Duration) error {
|
||||||
if r.appExistAndRunning(name) {
|
return r.wait(name, timeout, r.appExistAndRunning)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
timeoutTimer := time.After(timeout)
|
|
||||||
ticker := time.NewTicker(r.config.PollingWaitTime)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-timeoutTimer:
|
|
||||||
return ErrTimeoutError
|
|
||||||
case <-ticker.C:
|
|
||||||
if r.appExistAndRunning(name) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *marathonClient) appExistAndRunning(name string) bool {
|
func (r *marathonClient) appExistAndRunning(name string) bool {
|
||||||
|
@ -973,3 +964,22 @@ func (d *Discovery) AddPort(port Port) *Discovery {
|
||||||
d.Ports = &ports
|
d.Ports = &ports
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmptyNetworks explicitly empties networks
|
||||||
|
func (r *Application) EmptyNetworks() *Application {
|
||||||
|
r.Networks = &[]PodNetwork{}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNetwork sets the networking mode
|
||||||
|
func (r *Application) SetNetwork(name string, mode PodNetworkMode) *Application {
|
||||||
|
if r.Networks == nil {
|
||||||
|
r.EmptyNetworks()
|
||||||
|
}
|
||||||
|
|
||||||
|
network := PodNetwork{Name: name, Mode: mode}
|
||||||
|
networks := *r.Networks
|
||||||
|
networks = append(networks, network)
|
||||||
|
r.Networks = &networks
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
2
vendor/github.com/gambol99/go-marathon/application_marshalling.go
generated
vendored
2
vendor/github.com/gambol99/go-marathon/application_marshalling.go
generated
vendored
|
@ -61,7 +61,7 @@ func (app *Application) UnmarshalJSON(b []byte) error {
|
||||||
(*secrets)[secStore] = Secret{EnvVar: envName}
|
(*secrets)[secStore] = Secret{EnvVar: envName}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return fmt.Errorf("unexpected secret field %v or value type %T", secret, envValOrSecret[secret])
|
return fmt.Errorf("unexpected secret field %v of value type %T", secret, envValOrSecret[secret])
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unexpected environment variable type %T", envValOrSecret)
|
return fmt.Errorf("unexpected environment variable type %T", envValOrSecret)
|
||||||
|
|
76
vendor/github.com/gambol99/go-marathon/client.go
generated
vendored
76
vendor/github.com/gambol99/go-marathon/client.go
generated
vendored
|
@ -70,6 +70,40 @@ type Marathon interface {
|
||||||
// wait of application
|
// wait of application
|
||||||
WaitOnApplication(name string, timeout time.Duration) error
|
WaitOnApplication(name string, timeout time.Duration) error
|
||||||
|
|
||||||
|
// -- PODS ---
|
||||||
|
// whether this version of Marathon supports pods
|
||||||
|
SupportsPods() (bool, error)
|
||||||
|
|
||||||
|
// get pod status
|
||||||
|
PodStatus(name string) (*PodStatus, error)
|
||||||
|
// get all pod statuses
|
||||||
|
PodStatuses() ([]*PodStatus, error)
|
||||||
|
|
||||||
|
// get pod
|
||||||
|
Pod(name string) (*Pod, error)
|
||||||
|
// get all pods
|
||||||
|
Pods() ([]Pod, error)
|
||||||
|
// create pod
|
||||||
|
CreatePod(pod *Pod) (*Pod, error)
|
||||||
|
// update pod
|
||||||
|
UpdatePod(pod *Pod, force bool) (*Pod, error)
|
||||||
|
// delete pod
|
||||||
|
DeletePod(name string, force bool) (*DeploymentID, error)
|
||||||
|
// wait on pod to be deployed
|
||||||
|
WaitOnPod(name string, timeout time.Duration) error
|
||||||
|
// check if a pod is running
|
||||||
|
PodIsRunning(name string) bool
|
||||||
|
|
||||||
|
// get versions of a pod
|
||||||
|
PodVersions(name string) ([]string, error)
|
||||||
|
// get pod by version
|
||||||
|
PodByVersion(name, version string) (*Pod, error)
|
||||||
|
|
||||||
|
// delete instances of a pod
|
||||||
|
DeletePodInstances(name string, instances []string) ([]*PodInstance, error)
|
||||||
|
// delete pod instance
|
||||||
|
DeletePodInstance(name, instance string) (*PodInstance, error)
|
||||||
|
|
||||||
// -- TASKS ---
|
// -- TASKS ---
|
||||||
|
|
||||||
// get a list of tasks for a specific application
|
// get a list of tasks for a specific application
|
||||||
|
@ -273,6 +307,10 @@ func (r *marathonClient) Ping() (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *marathonClient) apiHead(path string, result interface{}) error {
|
||||||
|
return r.apiCall("HEAD", path, nil, result)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *marathonClient) apiGet(path string, post, result interface{}) error {
|
func (r *marathonClient) apiGet(path string, post, result interface{}) error {
|
||||||
return r.apiCall("GET", path, post, result)
|
return r.apiCall("GET", path, post, result)
|
||||||
}
|
}
|
||||||
|
@ -290,6 +328,8 @@ func (r *marathonClient) apiDelete(path string, post, result interface{}) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *marathonClient) apiCall(method, path string, body, result interface{}) error {
|
func (r *marathonClient) apiCall(method, path string, body, result interface{}) error {
|
||||||
|
const deploymentHeader = "Marathon-Deployment-Id"
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// step: marshall the request to json
|
// step: marshall the request to json
|
||||||
var requestBody []byte
|
var requestBody []byte
|
||||||
|
@ -328,13 +368,26 @@ func (r *marathonClient) apiCall(method, path string, body, result interface{})
|
||||||
r.debugLog("apiCall(): %v %v returned %v %s", request.Method, request.URL.String(), response.Status, oneLogLine(respBody))
|
r.debugLog("apiCall(): %v %v returned %v %s", request.Method, request.URL.String(), response.Status, oneLogLine(respBody))
|
||||||
}
|
}
|
||||||
|
|
||||||
// step: check for a successfull response
|
// step: check for a successful response
|
||||||
if response.StatusCode >= 200 && response.StatusCode <= 299 {
|
if response.StatusCode >= 200 && response.StatusCode <= 299 {
|
||||||
if result != nil {
|
if result != nil {
|
||||||
|
// If we have a deployment ID header and no response body, give them that
|
||||||
|
// This specifically handles the use case of a DELETE on an app/pod
|
||||||
|
// We need a way to retrieve the deployment ID
|
||||||
|
deploymentID := response.Header.Get(deploymentHeader)
|
||||||
|
if len(respBody) == 0 && deploymentID != "" {
|
||||||
|
d := DeploymentID{
|
||||||
|
DeploymentID: deploymentID,
|
||||||
|
}
|
||||||
|
if deployID, ok := result.(*DeploymentID); ok {
|
||||||
|
*deployID = d
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if err := json.Unmarshal(respBody, result); err != nil {
|
if err := json.Unmarshal(respBody, result); err != nil {
|
||||||
return fmt.Errorf("failed to unmarshal response from Marathon: %s", err)
|
return fmt.Errorf("failed to unmarshal response from Marathon: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,6 +403,27 @@ func (r *marathonClient) apiCall(method, path string, body, result interface{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait waits until the provided function returns true (or times out)
|
||||||
|
func (r *marathonClient) wait(name string, timeout time.Duration, fn func(string) bool) error {
|
||||||
|
timer := time.NewTimer(timeout)
|
||||||
|
defer timer.Stop()
|
||||||
|
|
||||||
|
ticker := time.NewTicker(r.config.PollingWaitTime)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
if fn(name) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
return ErrTimeoutError
|
||||||
|
case <-ticker.C:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// buildAPIRequest creates a default API request.
|
// buildAPIRequest creates a default API request.
|
||||||
// It fails when there is no available member in the cluster anymore or when the request can not be built.
|
// It fails when there is no available member in the cluster anymore or when the request can not be built.
|
||||||
func (r *marathonClient) buildAPIRequest(method, path 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) {
|
||||||
|
|
1
vendor/github.com/gambol99/go-marathon/const.go
generated
vendored
1
vendor/github.com/gambol99/go-marathon/const.go
generated
vendored
|
@ -24,6 +24,7 @@ const (
|
||||||
marathonAPIEventStream = marathonAPIVersion + "/events"
|
marathonAPIEventStream = marathonAPIVersion + "/events"
|
||||||
marathonAPISubscription = marathonAPIVersion + "/eventSubscriptions"
|
marathonAPISubscription = marathonAPIVersion + "/eventSubscriptions"
|
||||||
marathonAPIApps = marathonAPIVersion + "/apps"
|
marathonAPIApps = marathonAPIVersion + "/apps"
|
||||||
|
marathonAPIPods = marathonAPIVersion + "/pods"
|
||||||
marathonAPITasks = marathonAPIVersion + "/tasks"
|
marathonAPITasks = marathonAPIVersion + "/tasks"
|
||||||
marathonAPIDeployments = marathonAPIVersion + "/deployments"
|
marathonAPIDeployments = marathonAPIVersion + "/deployments"
|
||||||
marathonAPIGroups = marathonAPIVersion + "/groups"
|
marathonAPIGroups = marathonAPIVersion + "/groups"
|
||||||
|
|
12
vendor/github.com/gambol99/go-marathon/deployment.go
generated
vendored
12
vendor/github.com/gambol99/go-marathon/deployment.go
generated
vendored
|
@ -29,6 +29,7 @@ type Deployment struct {
|
||||||
CurrentStep int `json:"currentStep"`
|
CurrentStep int `json:"currentStep"`
|
||||||
TotalSteps int `json:"totalSteps"`
|
TotalSteps int `json:"totalSteps"`
|
||||||
AffectedApps []string `json:"affectedApps"`
|
AffectedApps []string `json:"affectedApps"`
|
||||||
|
AffectedPods []string `json:"affectedPods"`
|
||||||
Steps [][]*DeploymentStep `json:"-"`
|
Steps [][]*DeploymentStep `json:"-"`
|
||||||
XXStepsRaw json.RawMessage `json:"steps"` // Holds raw steps JSON to unmarshal later
|
XXStepsRaw json.RawMessage `json:"steps"` // Holds raw steps JSON to unmarshal later
|
||||||
CurrentActions []*DeploymentStep `json:"currentActions"`
|
CurrentActions []*DeploymentStep `json:"currentActions"`
|
||||||
|
@ -107,8 +108,17 @@ func (r *marathonClient) Deployments() ([]*Deployment, error) {
|
||||||
// id: the deployment id you wish to delete
|
// id: the deployment id you wish to delete
|
||||||
// force: whether or not to force the deletion
|
// force: whether or not to force the deletion
|
||||||
func (r *marathonClient) DeleteDeployment(id string, force bool) (*DeploymentID, error) {
|
func (r *marathonClient) DeleteDeployment(id string, force bool) (*DeploymentID, error) {
|
||||||
|
path := fmt.Sprintf("%s/%s", marathonAPIDeployments, id)
|
||||||
|
|
||||||
|
// if force=true, no body is returned
|
||||||
|
if force {
|
||||||
|
path += "?force=true"
|
||||||
|
return nil, r.apiDelete(path, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
deployment := new(DeploymentID)
|
deployment := new(DeploymentID)
|
||||||
err := r.apiDelete(fmt.Sprintf("%s/%s", marathonAPIDeployments, id), nil, deployment)
|
err := r.apiDelete(path, nil, deployment)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
93
vendor/github.com/gambol99/go-marathon/docker.go
generated
vendored
93
vendor/github.com/gambol99/go-marathon/docker.go
generated
vendored
|
@ -26,6 +26,7 @@ type Container struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Docker *Docker `json:"docker,omitempty"`
|
Docker *Docker `json:"docker,omitempty"`
|
||||||
Volumes *[]Volume `json:"volumes,omitempty"`
|
Volumes *[]Volume `json:"volumes,omitempty"`
|
||||||
|
PortMappings *[]PortMapping `json:"portMappings,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PortMapping is the portmapping structure between container and mesos
|
// PortMapping is the portmapping structure between container and mesos
|
||||||
|
@ -36,6 +37,7 @@ type PortMapping struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
ServicePort int `json:"servicePort,omitempty"`
|
ServicePort int `json:"servicePort,omitempty"`
|
||||||
Protocol string `json:"protocol,omitempty"`
|
Protocol string `json:"protocol,omitempty"`
|
||||||
|
NetworkNames *[]string `json:"networkNames,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameters is the parameters to pass to the docker client when creating the container
|
// Parameters is the parameters to pass to the docker client when creating the container
|
||||||
|
@ -53,11 +55,15 @@ type Volume struct {
|
||||||
Persistent *PersistentVolume `json:"persistent,omitempty"`
|
Persistent *PersistentVolume `json:"persistent,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PersistentVolumeType is the a persistent docker volume to be mounted
|
||||||
type PersistentVolumeType string
|
type PersistentVolumeType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// PersistentVolumeTypeRoot is the root path of the persistent volume
|
||||||
PersistentVolumeTypeRoot PersistentVolumeType = "root"
|
PersistentVolumeTypeRoot PersistentVolumeType = "root"
|
||||||
|
// PersistentVolumeTypePath is the mount path of the persistent volume
|
||||||
PersistentVolumeTypePath PersistentVolumeType = "path"
|
PersistentVolumeTypePath PersistentVolumeType = "path"
|
||||||
|
// PersistentVolumeTypeMount is the mount type of the persistent volume
|
||||||
PersistentVolumeTypeMount PersistentVolumeType = "mount"
|
PersistentVolumeTypeMount PersistentVolumeType = "mount"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -255,6 +261,19 @@ func (docker *Docker) Host() *Docker {
|
||||||
return docker
|
return docker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose sets the container to expose the following TCP ports
|
||||||
|
// ports: the TCP ports the container is exposing
|
||||||
|
func (container *Container) Expose(ports ...int) *Container {
|
||||||
|
for _, port := range ports {
|
||||||
|
container.ExposePort(PortMapping{
|
||||||
|
ContainerPort: port,
|
||||||
|
HostPort: 0,
|
||||||
|
ServicePort: 0,
|
||||||
|
Protocol: "tcp"})
|
||||||
|
}
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
|
||||||
// Expose sets the container to expose the following TCP ports
|
// Expose sets the container to expose the following TCP ports
|
||||||
// ports: the TCP ports the container is exposing
|
// ports: the TCP ports the container is exposing
|
||||||
func (docker *Docker) Expose(ports ...int) *Docker {
|
func (docker *Docker) Expose(ports ...int) *Docker {
|
||||||
|
@ -268,6 +287,19 @@ func (docker *Docker) Expose(ports ...int) *Docker {
|
||||||
return docker
|
return docker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExposeUDP sets the container to expose the following UDP ports
|
||||||
|
// ports: the UDP ports the container is exposing
|
||||||
|
func (container *Container) ExposeUDP(ports ...int) *Container {
|
||||||
|
for _, port := range ports {
|
||||||
|
container.ExposePort(PortMapping{
|
||||||
|
ContainerPort: port,
|
||||||
|
HostPort: 0,
|
||||||
|
ServicePort: 0,
|
||||||
|
Protocol: "udp"})
|
||||||
|
}
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
|
||||||
// ExposeUDP sets the container to expose the following UDP ports
|
// ExposeUDP sets the container to expose the following UDP ports
|
||||||
// ports: the UDP ports the container is exposing
|
// ports: the UDP ports the container is exposing
|
||||||
func (docker *Docker) ExposeUDP(ports ...int) *Docker {
|
func (docker *Docker) ExposeUDP(ports ...int) *Docker {
|
||||||
|
@ -281,6 +313,19 @@ func (docker *Docker) ExposeUDP(ports ...int) *Docker {
|
||||||
return docker
|
return docker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExposePort exposes an port in the container
|
||||||
|
func (container *Container) ExposePort(portMapping PortMapping) *Container {
|
||||||
|
if container.PortMappings == nil {
|
||||||
|
container.EmptyPortMappings()
|
||||||
|
}
|
||||||
|
|
||||||
|
portMappings := *container.PortMappings
|
||||||
|
portMappings = append(portMappings, portMapping)
|
||||||
|
container.PortMappings = &portMappings
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
|
||||||
// ExposePort exposes an port in the container
|
// ExposePort exposes an port in the container
|
||||||
func (docker *Docker) ExposePort(portMapping PortMapping) *Docker {
|
func (docker *Docker) ExposePort(portMapping PortMapping) *Docker {
|
||||||
if docker.PortMappings == nil {
|
if docker.PortMappings == nil {
|
||||||
|
@ -294,6 +339,14 @@ func (docker *Docker) ExposePort(portMapping PortMapping) *Docker {
|
||||||
return docker
|
return docker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmptyPortMappings explicitly empties the port mappings -- use this if you need to empty
|
||||||
|
// port mappings of an application that already has port mappings set (setting port mappings to nil will
|
||||||
|
// keep the current value)
|
||||||
|
func (container *Container) EmptyPortMappings() *Container {
|
||||||
|
container.PortMappings = &[]PortMapping{}
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
|
||||||
// EmptyPortMappings explicitly empties the port mappings -- use this if you need to empty
|
// EmptyPortMappings explicitly empties the port mappings -- use this if you need to empty
|
||||||
// port mappings of an application that already has port mappings set (setting port mappings to nil will
|
// port mappings of an application that already has port mappings set (setting port mappings to nil will
|
||||||
// keep the current value)
|
// keep the current value)
|
||||||
|
@ -349,6 +402,24 @@ func (docker *Docker) EmptyParameters() *Docker {
|
||||||
return docker
|
return docker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServicePortIndex finds the service port index of the exposed port
|
||||||
|
// port: the port you are looking for
|
||||||
|
func (container *Container) ServicePortIndex(port int) (int, error) {
|
||||||
|
if container.PortMappings == nil || len(*container.PortMappings) == 0 {
|
||||||
|
return 0, errors.New("The container does not contain any port mappings to search")
|
||||||
|
}
|
||||||
|
|
||||||
|
// step: iterate and find the port
|
||||||
|
for index, containerPort := range *container.PortMappings {
|
||||||
|
if containerPort.ContainerPort == port {
|
||||||
|
return index, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// step: we didn't find the port in the mappings
|
||||||
|
return 0, fmt.Errorf("The container port %d was not found in the container port mappings", port)
|
||||||
|
}
|
||||||
|
|
||||||
// ServicePortIndex finds the service port index of the exposed port
|
// ServicePortIndex finds the service port index of the exposed port
|
||||||
// port: the port you are looking for
|
// port: the port you are looking for
|
||||||
func (docker *Docker) ServicePortIndex(port int) (int, error) {
|
func (docker *Docker) ServicePortIndex(port int) (int, error) {
|
||||||
|
@ -364,5 +435,25 @@ func (docker *Docker) ServicePortIndex(port int) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// step: we didn't find the port in the mappings
|
// step: we didn't find the port in the mappings
|
||||||
return 0, fmt.Errorf("The container port required was not found in the container port mappings")
|
return 0, fmt.Errorf("The docker port %d was not found in the container port mappings", port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNetwork adds a network name to a PortMapping
|
||||||
|
// name: the name of the network
|
||||||
|
func (p *PortMapping) AddNetwork(name string) *PortMapping {
|
||||||
|
if p.NetworkNames == nil {
|
||||||
|
p.EmptyNetworkNames()
|
||||||
|
}
|
||||||
|
networks := *p.NetworkNames
|
||||||
|
networks = append(networks, name)
|
||||||
|
p.NetworkNames = &networks
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyNetworkNames explicitly empties the network names -- use this if you need to empty
|
||||||
|
// the network names of a port mapping that already has network names set
|
||||||
|
func (p *PortMapping) EmptyNetworkNames() *PortMapping {
|
||||||
|
p.NetworkNames = &[]string{}
|
||||||
|
|
||||||
|
return p
|
||||||
}
|
}
|
||||||
|
|
4
vendor/github.com/gambol99/go-marathon/error.go
generated
vendored
4
vendor/github.com/gambol99/go-marathon/error.go
generated
vendored
|
@ -42,6 +42,8 @@ const (
|
||||||
ErrCodeServer
|
ErrCodeServer
|
||||||
// ErrCodeUnknown specifies an unknown error.
|
// ErrCodeUnknown specifies an unknown error.
|
||||||
ErrCodeUnknown
|
ErrCodeUnknown
|
||||||
|
// ErrCodeMethodNotAllowed specifies a 405 Method Not Allowed.
|
||||||
|
ErrCodeMethodNotAllowed
|
||||||
)
|
)
|
||||||
|
|
||||||
// InvalidEndpointError indicates a endpoint error in the marathon urls
|
// InvalidEndpointError indicates a endpoint error in the marathon urls
|
||||||
|
@ -82,6 +84,8 @@ func NewAPIError(code int, content []byte) error {
|
||||||
errDef = &simpleErrDef{code: ErrCodeForbidden}
|
errDef = &simpleErrDef{code: ErrCodeForbidden}
|
||||||
case code == http.StatusNotFound:
|
case code == http.StatusNotFound:
|
||||||
errDef = &simpleErrDef{code: ErrCodeNotFound}
|
errDef = &simpleErrDef{code: ErrCodeNotFound}
|
||||||
|
case code == http.StatusMethodNotAllowed:
|
||||||
|
errDef = &simpleErrDef{code: ErrCodeMethodNotAllowed}
|
||||||
case code == http.StatusConflict:
|
case code == http.StatusConflict:
|
||||||
errDef = &conflictDef{}
|
errDef = &conflictDef{}
|
||||||
case code == 422:
|
case code == 422:
|
||||||
|
|
29
vendor/github.com/gambol99/go-marathon/health.go
generated
vendored
29
vendor/github.com/gambol99/go-marathon/health.go
generated
vendored
|
@ -30,6 +30,35 @@ type HealthCheck struct {
|
||||||
IgnoreHTTP1xx *bool `json:"ignoreHttp1xx,omitempty"`
|
IgnoreHTTP1xx *bool `json:"ignoreHttp1xx,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTPHealthCheck describes an HTTP based health check
|
||||||
|
type HTTPHealthCheck struct {
|
||||||
|
Endpoint string `json:"endpoint,omitempty"`
|
||||||
|
Path string `json:"path,omitempty"`
|
||||||
|
Scheme string `json:"scheme,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCPHealthCheck describes a TCP based health check
|
||||||
|
type TCPHealthCheck struct {
|
||||||
|
Endpoint string `json:"endpoint,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandHealthCheck describes a shell-based health check
|
||||||
|
type CommandHealthCheck struct {
|
||||||
|
Command PodCommand `json:"command,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodHealthCheck describes how to determine a pod's health
|
||||||
|
type PodHealthCheck struct {
|
||||||
|
HTTP *HTTPHealthCheck `json:"http,omitempty"`
|
||||||
|
TCP *TCPHealthCheck `json:"tcp,omitempty"`
|
||||||
|
Exec *CommandHealthCheck `json:"exec,omitempty"`
|
||||||
|
GracePeriodSeconds *int `json:"gracePeriodSeconds,omitempty"`
|
||||||
|
IntervalSeconds *int `json:"intervalSeconds,omitempty"`
|
||||||
|
MaxConsecutiveFailures *int `json:"maxConsecutiveFailures,omitempty"`
|
||||||
|
TimeoutSeconds *int `json:"timeoutSeconds,omitempty"`
|
||||||
|
DelaySeconds *int `json:"delaySeconds,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// SetCommand sets the given command on the health check.
|
// SetCommand sets the given command on the health check.
|
||||||
func (h *HealthCheck) SetCommand(c Command) *HealthCheck {
|
func (h *HealthCheck) SetCommand(c Command) *HealthCheck {
|
||||||
h.Command = &c
|
h.Command = &c
|
||||||
|
|
124
vendor/github.com/gambol99/go-marathon/network.go
generated
vendored
Normal file
124
vendor/github.com/gambol99/go-marathon/network.go
generated
vendored
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
// PodNetworkMode is the mode of a network descriptor
|
||||||
|
type PodNetworkMode string
|
||||||
|
|
||||||
|
const (
|
||||||
|
ContainerNetworkMode PodNetworkMode = "container"
|
||||||
|
BridgeNetworkMode PodNetworkMode = "container/bridge"
|
||||||
|
HostNetworkMode PodNetworkMode = "host"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodNetwork contains network descriptors for a pod
|
||||||
|
type PodNetwork struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Mode PodNetworkMode `json:"mode,omitempty"`
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodEndpoint describes an endpoint for a pod's container
|
||||||
|
type PodEndpoint struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
ContainerPort int `json:"containerPort,omitempty"`
|
||||||
|
HostPort int `json:"hostPort,omitempty"`
|
||||||
|
Protocol []string `json:"protocol,omitempty"`
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodNetwork creates an empty PodNetwork
|
||||||
|
func NewPodNetwork(name string) *PodNetwork {
|
||||||
|
return &PodNetwork{
|
||||||
|
Name: name,
|
||||||
|
Labels: map[string]string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodEndpoint creates an empty PodEndpoint
|
||||||
|
func NewPodEndpoint() *PodEndpoint {
|
||||||
|
return &PodEndpoint{
|
||||||
|
Protocol: []string{},
|
||||||
|
Labels: map[string]string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBridgePodNetwork creates a PodNetwork for a container in bridge mode
|
||||||
|
func NewBridgePodNetwork() *PodNetwork {
|
||||||
|
pn := NewPodNetwork("")
|
||||||
|
return pn.SetMode(BridgeNetworkMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContainerPodNetwork creates a PodNetwork for a container
|
||||||
|
func NewContainerPodNetwork(name string) *PodNetwork {
|
||||||
|
pn := NewPodNetwork(name)
|
||||||
|
return pn.SetMode(ContainerNetworkMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewHostPodNetwork creates a PodNetwork for a container in host mode
|
||||||
|
func NewHostPodNetwork() *PodNetwork {
|
||||||
|
pn := NewPodNetwork("")
|
||||||
|
return pn.SetMode(HostNetworkMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the name of a PodNetwork
|
||||||
|
func (n *PodNetwork) SetName(name string) *PodNetwork {
|
||||||
|
n.Name = name
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMode sets the mode of a PodNetwork
|
||||||
|
func (n *PodNetwork) SetMode(mode PodNetworkMode) *PodNetwork {
|
||||||
|
n.Mode = mode
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label sets a label of a PodNetwork
|
||||||
|
func (n *PodNetwork) Label(key, value string) *PodNetwork {
|
||||||
|
n.Labels[key] = value
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the name for a PodEndpoint
|
||||||
|
func (e *PodEndpoint) SetName(name string) *PodEndpoint {
|
||||||
|
e.Name = name
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetContainerPort sets the container port for a PodEndpoint
|
||||||
|
func (e *PodEndpoint) SetContainerPort(port int) *PodEndpoint {
|
||||||
|
e.ContainerPort = port
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHostPort sets the host port for a PodEndpoint
|
||||||
|
func (e *PodEndpoint) SetHostPort(port int) *PodEndpoint {
|
||||||
|
e.HostPort = port
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddProtocol appends a protocol for a PodEndpoint
|
||||||
|
func (e *PodEndpoint) AddProtocol(protocol string) *PodEndpoint {
|
||||||
|
e.Protocol = append(e.Protocol, protocol)
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Label sets a label for a PodEndpoint
|
||||||
|
func (e *PodEndpoint) Label(key, value string) *PodEndpoint {
|
||||||
|
e.Labels[key] = value
|
||||||
|
return e
|
||||||
|
}
|
277
vendor/github.com/gambol99/go-marathon/pod.go
generated
vendored
Normal file
277
vendor/github.com/gambol99/go-marathon/pod.go
generated
vendored
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pod is the definition for an pod in marathon
|
||||||
|
type Pod struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
Version string `json:"version,omitempty"`
|
||||||
|
User string `json:"user,omitempty"`
|
||||||
|
// Non-secret environment variables. Actual secrets are stored in Secrets
|
||||||
|
// Magic happens at marshaling/unmarshaling to get them into the correct schema
|
||||||
|
Env map[string]string `json:"-"`
|
||||||
|
Secrets map[string]Secret `json:"-"`
|
||||||
|
Containers []*PodContainer `json:"containers,omitempty"`
|
||||||
|
Volumes []*PodVolume `json:"volumes,omitempty"`
|
||||||
|
Networks []*PodNetwork `json:"networks,omitempty"`
|
||||||
|
Scaling *PodScalingPolicy `json:"scaling,omitempty"`
|
||||||
|
Scheduling *PodSchedulingPolicy `json:"scheduling,omitempty"`
|
||||||
|
ExecutorResources *ExecutorResources `json:"executorResources,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodScalingPolicy is the scaling policy of the pod
|
||||||
|
type PodScalingPolicy struct {
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
Instances int `json:"instances"`
|
||||||
|
MaxInstances int `json:"maxInstances,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPod create an empty pod
|
||||||
|
func NewPod() *Pod {
|
||||||
|
return &Pod{
|
||||||
|
Labels: map[string]string{},
|
||||||
|
Env: map[string]string{},
|
||||||
|
Containers: []*PodContainer{},
|
||||||
|
Secrets: map[string]Secret{},
|
||||||
|
Volumes: []*PodVolume{},
|
||||||
|
Networks: []*PodNetwork{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name sets the name / ID of the pod i.e. the identifier for this pod
|
||||||
|
func (p *Pod) Name(id string) *Pod {
|
||||||
|
p.ID = validateID(id)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUser sets the user to run the pod as
|
||||||
|
func (p *Pod) SetUser(user string) *Pod {
|
||||||
|
p.User = user
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyLabels empties the labels in a pod
|
||||||
|
func (p *Pod) EmptyLabels() *Pod {
|
||||||
|
p.Labels = make(map[string]string)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLabel adds a label to a pod
|
||||||
|
func (p *Pod) AddLabel(key, value string) *Pod {
|
||||||
|
p.Labels[key] = value
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLabels sets the labels for a pod
|
||||||
|
func (p *Pod) SetLabels(labels map[string]string) *Pod {
|
||||||
|
p.Labels = labels
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyEnvs empties the environment variables for a pod
|
||||||
|
func (p *Pod) EmptyEnvs() *Pod {
|
||||||
|
p.Env = make(map[string]string)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEnv adds an environment variable to a pod
|
||||||
|
func (p *Pod) AddEnv(name, value string) *Pod {
|
||||||
|
if p.Env == nil {
|
||||||
|
p = p.EmptyEnvs()
|
||||||
|
}
|
||||||
|
p.Env[name] = value
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtendEnv extends the environment with the new environment variables
|
||||||
|
func (p *Pod) ExtendEnv(env map[string]string) *Pod {
|
||||||
|
if p.Env == nil {
|
||||||
|
p = p.EmptyEnvs()
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range env {
|
||||||
|
p.AddEnv(k, v)
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddContainer adds a container to a pod
|
||||||
|
func (p *Pod) AddContainer(container *PodContainer) *Pod {
|
||||||
|
p.Containers = append(p.Containers, container)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptySecrets empties the secret sources in a pod
|
||||||
|
func (p *Pod) EmptySecrets() *Pod {
|
||||||
|
p.Secrets = make(map[string]Secret)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSecretSource gets the source of the named secret
|
||||||
|
func (p *Pod) GetSecretSource(name string) (string, error) {
|
||||||
|
if val, ok := p.Secrets[name]; ok {
|
||||||
|
return val.Source, nil
|
||||||
|
}
|
||||||
|
return "", fmt.Errorf("secret does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSecret adds the secret to the pod
|
||||||
|
func (p *Pod) AddSecret(envVar, secretName, sourceName string) *Pod {
|
||||||
|
if p.Secrets == nil {
|
||||||
|
p = p.EmptySecrets()
|
||||||
|
}
|
||||||
|
p.Secrets[secretName] = Secret{EnvVar: envVar, Source: sourceName}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddVolume adds a volume to a pod
|
||||||
|
func (p *Pod) AddVolume(vol *PodVolume) *Pod {
|
||||||
|
p.Volumes = append(p.Volumes, vol)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddNetwork adds a PodNetwork to a pod
|
||||||
|
func (p *Pod) AddNetwork(net *PodNetwork) *Pod {
|
||||||
|
p.Networks = append(p.Networks, net)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count sets the count of the pod
|
||||||
|
func (p *Pod) Count(count int) *Pod {
|
||||||
|
p.Scaling = &PodScalingPolicy{
|
||||||
|
Kind: "fixed",
|
||||||
|
Instances: count,
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPodSchedulingPolicy sets the PodSchedulingPolicy of a pod
|
||||||
|
func (p *Pod) SetPodSchedulingPolicy(policy *PodSchedulingPolicy) *Pod {
|
||||||
|
p.Scheduling = policy
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExecutorResources sets the resources for the pod executor
|
||||||
|
func (p *Pod) SetExecutorResources(resources *ExecutorResources) *Pod {
|
||||||
|
p.ExecutorResources = resources
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SupportsPods determines if this version of marathon supports pods
|
||||||
|
// If HEAD returns 200 it does
|
||||||
|
func (r *marathonClient) SupportsPods() (bool, error) {
|
||||||
|
if err := r.apiHead(marathonAPIPods, nil); err != nil {
|
||||||
|
// If we get a 404 we can return a strict false, otherwise it could be
|
||||||
|
// a valid error
|
||||||
|
if apiErr, ok := err.(*APIError); ok && apiErr.ErrCode == ErrCodeNotFound {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pod gets a pod object from marathon by name
|
||||||
|
func (r *marathonClient) Pod(name string) (*Pod, error) {
|
||||||
|
uri := buildPodURI(name)
|
||||||
|
result := new(Pod)
|
||||||
|
if err := r.apiGet(uri, nil, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pods gets all pods from marathon
|
||||||
|
func (r *marathonClient) Pods() ([]Pod, error) {
|
||||||
|
var result []Pod
|
||||||
|
if err := r.apiGet(marathonAPIPods, nil, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatePod creates a new pod in Marathon
|
||||||
|
func (r *marathonClient) CreatePod(pod *Pod) (*Pod, error) {
|
||||||
|
result := new(Pod)
|
||||||
|
if err := r.apiPost(marathonAPIPods, &pod, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePod deletes a pod from marathon
|
||||||
|
func (r *marathonClient) DeletePod(name string, force bool) (*DeploymentID, error) {
|
||||||
|
uri := fmt.Sprintf("%s?force=%v", buildPodURI(name), force)
|
||||||
|
|
||||||
|
deployID := new(DeploymentID)
|
||||||
|
if err := r.apiDelete(uri, nil, deployID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return deployID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatePod creates a new pod in Marathon
|
||||||
|
func (r *marathonClient) UpdatePod(pod *Pod, force bool) (*Pod, error) {
|
||||||
|
uri := fmt.Sprintf("%s?force=%v", buildPodURI(pod.ID), force)
|
||||||
|
result := new(Pod)
|
||||||
|
|
||||||
|
if err := r.apiPut(uri, pod, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodVersions gets all the deployed versions of a pod
|
||||||
|
func (r *marathonClient) PodVersions(name string) ([]string, error) {
|
||||||
|
uri := buildPodVersionURI(name)
|
||||||
|
var result []string
|
||||||
|
if err := r.apiGet(uri, nil, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodByVersion gets a pod by a version identifier
|
||||||
|
func (r *marathonClient) PodByVersion(name, version string) (*Pod, error) {
|
||||||
|
uri := fmt.Sprintf("%s/%s", buildPodVersionURI(name), version)
|
||||||
|
result := new(Pod)
|
||||||
|
if err := r.apiGet(uri, nil, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPodVersionURI(name string) string {
|
||||||
|
return fmt.Sprintf("%s/%s::versions", marathonAPIPods, trimRootPath(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPodURI(path string) string {
|
||||||
|
return fmt.Sprintf("%s/%s", marathonAPIPods, trimRootPath(path))
|
||||||
|
}
|
193
vendor/github.com/gambol99/go-marathon/pod_container.go
generated
vendored
Normal file
193
vendor/github.com/gambol99/go-marathon/pod_container.go
generated
vendored
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
// PodContainer describes a container in a pod
|
||||||
|
type PodContainer struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Exec *PodExec `json:"exec,omitempty"`
|
||||||
|
Resources *Resources `json:"resources,omitempty"`
|
||||||
|
Endpoints []*PodEndpoint `json:"endpoints,omitempty"`
|
||||||
|
Image *PodContainerImage `json:"image,omitempty"`
|
||||||
|
Env map[string]string `json:"-"`
|
||||||
|
Secrets map[string]Secret `json:"-"`
|
||||||
|
User string `json:"user,omitempty"`
|
||||||
|
HealthCheck *PodHealthCheck `json:"healthCheck,omitempty"`
|
||||||
|
VolumeMounts []*PodVolumeMount `json:"volumeMounts,omitempty"`
|
||||||
|
Artifacts []*PodArtifact `json:"artifacts,omitempty"`
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
Lifecycle PodLifecycle `json:"lifecycle,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodLifecycle describes the lifecycle of a pod
|
||||||
|
type PodLifecycle struct {
|
||||||
|
KillGracePeriodSeconds *float64 `json:"killGracePeriodSeconds,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodCommand is the command to run as the entrypoint of the container
|
||||||
|
type PodCommand struct {
|
||||||
|
Shell string `json:"shell,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodExec contains the PodCommand
|
||||||
|
type PodExec struct {
|
||||||
|
Command PodCommand `json:"command,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodArtifact describes how to obtain a generic artifact for a pod
|
||||||
|
type PodArtifact struct {
|
||||||
|
URI string `json:"uri,omitempty"`
|
||||||
|
Extract bool `json:"extract,omitempty"`
|
||||||
|
Executable bool `json:"executable,omitempty"`
|
||||||
|
Cache bool `json:"cache,omitempty"`
|
||||||
|
DestPath string `json:"destPath,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodContainer creates an empty PodContainer
|
||||||
|
func NewPodContainer() *PodContainer {
|
||||||
|
return &PodContainer{
|
||||||
|
Endpoints: []*PodEndpoint{},
|
||||||
|
Env: map[string]string{},
|
||||||
|
VolumeMounts: []*PodVolumeMount{},
|
||||||
|
Artifacts: []*PodArtifact{},
|
||||||
|
Labels: map[string]string{},
|
||||||
|
Resources: NewResources(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetName sets the name of a pod container
|
||||||
|
func (p *PodContainer) SetName(name string) *PodContainer {
|
||||||
|
p.Name = name
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCommand sets the shell command of a pod container
|
||||||
|
func (p *PodContainer) SetCommand(name string) *PodContainer {
|
||||||
|
p.Exec = &PodExec{
|
||||||
|
Command: PodCommand{
|
||||||
|
Shell: name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPUs sets the CPUs of a pod container
|
||||||
|
func (p *PodContainer) CPUs(cpu float64) *PodContainer {
|
||||||
|
p.Resources.Cpus = cpu
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Memory sets the memory of a pod container
|
||||||
|
func (p *PodContainer) Memory(memory float64) *PodContainer {
|
||||||
|
p.Resources.Mem = memory
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Storage sets the storage capacity of a pod container
|
||||||
|
func (p *PodContainer) Storage(disk float64) *PodContainer {
|
||||||
|
p.Resources.Disk = disk
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPUs sets the GPU requirements of a pod container
|
||||||
|
func (p *PodContainer) GPUs(gpu int32) *PodContainer {
|
||||||
|
p.Resources.Gpus = gpu
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEndpoint appends an endpoint for a pod container
|
||||||
|
func (p *PodContainer) AddEndpoint(endpoint *PodEndpoint) *PodContainer {
|
||||||
|
p.Endpoints = append(p.Endpoints, endpoint)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetImage sets the image of a pod container
|
||||||
|
func (p *PodContainer) SetImage(image *PodContainerImage) *PodContainer {
|
||||||
|
p.Image = image
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// EmptyEnvironment initialized env to empty
|
||||||
|
func (p *PodContainer) EmptyEnvs() *PodContainer {
|
||||||
|
p.Env = make(map[string]string)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddEnvironment adds an environment variable for a pod container
|
||||||
|
func (p *PodContainer) AddEnv(name, value string) *PodContainer {
|
||||||
|
if p.Env == nil {
|
||||||
|
p = p.EmptyEnvs()
|
||||||
|
}
|
||||||
|
p.Env[name] = value
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtendEnvironment extends the environment for a pod container
|
||||||
|
func (p *PodContainer) ExtendEnv(env map[string]string) *PodContainer {
|
||||||
|
if p.Env == nil {
|
||||||
|
p = p.EmptyEnvs()
|
||||||
|
}
|
||||||
|
for k, v := range env {
|
||||||
|
p.AddEnv(k, v)
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSecret adds a secret to the environment for a pod container
|
||||||
|
func (p *PodContainer) AddSecret(name, secretName string) *PodContainer {
|
||||||
|
if p.Env == nil {
|
||||||
|
p = p.EmptyEnvs()
|
||||||
|
}
|
||||||
|
p.Env[name] = secretName
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetUser sets the user to run the pod as
|
||||||
|
func (p *PodContainer) SetUser(user string) *PodContainer {
|
||||||
|
p.User = user
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHealthCheck sets the health check of a pod container
|
||||||
|
func (p *PodContainer) SetHealthCheck(healthcheck *PodHealthCheck) *PodContainer {
|
||||||
|
p.HealthCheck = healthcheck
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddVolumeMount appends a volume mount to a pod container
|
||||||
|
func (p *PodContainer) AddVolumeMount(mount *PodVolumeMount) *PodContainer {
|
||||||
|
p.VolumeMounts = append(p.VolumeMounts, mount)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddArtifact appends an artifact to a pod container
|
||||||
|
func (p *PodContainer) AddArtifact(artifact *PodArtifact) *PodContainer {
|
||||||
|
p.Artifacts = append(p.Artifacts, artifact)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddLabel adds a label to a pod container
|
||||||
|
func (p *PodContainer) AddLabel(key, value string) *PodContainer {
|
||||||
|
p.Labels[key] = value
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLifecycle sets the lifecycle of a pod container
|
||||||
|
func (p *PodContainer) SetLifecycle(lifecycle PodLifecycle) *PodContainer {
|
||||||
|
p.Lifecycle = lifecycle
|
||||||
|
return p
|
||||||
|
}
|
57
vendor/github.com/gambol99/go-marathon/pod_container_image.go
generated
vendored
Normal file
57
vendor/github.com/gambol99/go-marathon/pod_container_image.go
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
// ImageType represents the image format type
|
||||||
|
type ImageType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ImageTypeDocker is the docker format
|
||||||
|
ImageTypeDocker ImageType = "DOCKER"
|
||||||
|
|
||||||
|
// ImageTypeAppC is the appc format
|
||||||
|
ImageTypeAppC ImageType = "APPC"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodContainerImage describes how to retrieve the container image
|
||||||
|
type PodContainerImage struct {
|
||||||
|
Kind ImageType `json:"kind,omitempty"`
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
ForcePull bool `json:"forcePull,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodContainerImage creates an empty PodContainerImage
|
||||||
|
func NewPodContainerImage() *PodContainerImage {
|
||||||
|
return &PodContainerImage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetKind sets the Kind of the image
|
||||||
|
func (i *PodContainerImage) SetKind(typ ImageType) *PodContainerImage {
|
||||||
|
i.Kind = typ
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetID sets the ID of the image
|
||||||
|
func (i *PodContainerImage) SetID(id string) *PodContainerImage {
|
||||||
|
i.ID = id
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDockerPodContainerImage creates a docker PodContainerImage
|
||||||
|
func NewDockerPodContainerImage() *PodContainerImage {
|
||||||
|
return NewPodContainerImage().SetKind(ImageTypeDocker)
|
||||||
|
}
|
94
vendor/github.com/gambol99/go-marathon/pod_container_marshalling.go
generated
vendored
Normal file
94
vendor/github.com/gambol99/go-marathon/pod_container_marshalling.go
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodContainerAlias aliases the PodContainer struct so that it will be marshaled/unmarshaled automatically
|
||||||
|
type PodContainerAlias PodContainer
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals the given PodContainer JSON as expected except for environment variables and secrets.
|
||||||
|
// Environment variables are stored in the Env field. Secrets, including the environment variable part,
|
||||||
|
// are stored in the Secrets field.
|
||||||
|
func (p *PodContainer) UnmarshalJSON(b []byte) error {
|
||||||
|
aux := &struct {
|
||||||
|
*PodContainerAlias
|
||||||
|
Env map[string]interface{} `json:"environment"`
|
||||||
|
}{
|
||||||
|
PodContainerAlias: (*PodContainerAlias)(p),
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(b, aux); err != nil {
|
||||||
|
return fmt.Errorf("malformed pod container definition %v", err)
|
||||||
|
}
|
||||||
|
env := map[string]string{}
|
||||||
|
secrets := map[string]Secret{}
|
||||||
|
|
||||||
|
for envName, genericEnvValue := range aux.Env {
|
||||||
|
switch envValOrSecret := genericEnvValue.(type) {
|
||||||
|
case string:
|
||||||
|
env[envName] = envValOrSecret
|
||||||
|
case map[string]interface{}:
|
||||||
|
for secret, secretStore := range envValOrSecret {
|
||||||
|
if secStore, ok := secretStore.(string); ok && secret == "secret" {
|
||||||
|
secrets[secStore] = Secret{EnvVar: envName}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unexpected secret field %v of value type %T", secret, envValOrSecret[secret])
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected environment variable type %T", envValOrSecret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Env = env
|
||||||
|
for k, v := range aux.Secrets {
|
||||||
|
tmp := secrets[k]
|
||||||
|
tmp.Source = v.Source
|
||||||
|
secrets[k] = tmp
|
||||||
|
}
|
||||||
|
p.Secrets = secrets
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON marshals the given PodContainer as expected except for environment variables and secrets,
|
||||||
|
// which are marshaled from specialized structs. The environment variable piece of the secrets and other
|
||||||
|
// normal environment variables are combined and marshaled to the env field. The secrets and the related
|
||||||
|
// source are marshaled into the secrets field.
|
||||||
|
func (p *PodContainer) MarshalJSON() ([]byte, error) {
|
||||||
|
env := make(map[string]interface{})
|
||||||
|
secrets := make(map[string]TmpSecret)
|
||||||
|
|
||||||
|
if p.Env != nil {
|
||||||
|
for k, v := range p.Env {
|
||||||
|
env[string(k)] = string(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Secrets != nil {
|
||||||
|
for k, v := range p.Secrets {
|
||||||
|
env[v.EnvVar] = TmpEnvSecret{Secret: k}
|
||||||
|
secrets[k] = TmpSecret{v.Source}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aux := &struct {
|
||||||
|
*PodContainerAlias
|
||||||
|
Env map[string]interface{} `json:"environment,omitempty"`
|
||||||
|
}{PodContainerAlias: (*PodContainerAlias)(p), Env: env}
|
||||||
|
|
||||||
|
return json.Marshal(aux)
|
||||||
|
}
|
105
vendor/github.com/gambol99/go-marathon/pod_instance.go
generated
vendored
Normal file
105
vendor/github.com/gambol99/go-marathon/pod_instance.go
generated
vendored
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodInstance is the representation of an instance as returned by deleting an instance
|
||||||
|
type PodInstance struct {
|
||||||
|
InstanceID PodInstanceID `json:"instanceId"`
|
||||||
|
AgentInfo PodAgentInfo `json:"agentInfo"`
|
||||||
|
TasksMap map[string]PodTask `json:"tasksMap"`
|
||||||
|
RunSpecVersion time.Time `json:"runSpecVersion"`
|
||||||
|
State PodInstanceStateHistory `json:"state"`
|
||||||
|
UnreachableStrategy EnabledUnreachableStrategy `json:"unreachableStrategy"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodInstanceStateHistory is the pod instance's state
|
||||||
|
type PodInstanceStateHistory struct {
|
||||||
|
Condition PodTaskCondition `json:"condition"`
|
||||||
|
Since time.Time `json:"since"`
|
||||||
|
ActiveSince time.Time `json:"activeSince"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodInstanceID contains the instance ID
|
||||||
|
type PodInstanceID struct {
|
||||||
|
ID string `json:"idString"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodAgentInfo contains info about the agent the instance is running on
|
||||||
|
type PodAgentInfo struct {
|
||||||
|
Host string `json:"host"`
|
||||||
|
AgentID string `json:"agentId"`
|
||||||
|
Attributes []string `json:"attributes"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodTask contains the info about the specific task within the instance
|
||||||
|
type PodTask struct {
|
||||||
|
TaskID string `json:"taskId"`
|
||||||
|
RunSpecVersion time.Time `json:"runSpecVersion"`
|
||||||
|
Status PodTaskStatus `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodTaskStatus is the current status of the task
|
||||||
|
type PodTaskStatus struct {
|
||||||
|
StagedAt time.Time `json:"stagedAt"`
|
||||||
|
StartedAt time.Time `json:"startedAt"`
|
||||||
|
MesosStatus string `json:"mesosStatus"`
|
||||||
|
Condition PodTaskCondition `json:"condition"`
|
||||||
|
NetworkInfo PodNetworkInfo `json:"networkInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodTaskCondition contains a string representation of the condition
|
||||||
|
type PodTaskCondition struct {
|
||||||
|
Str string `json:"str"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodNetworkInfo contains the network info for a task
|
||||||
|
type PodNetworkInfo struct {
|
||||||
|
HostName string `json:"hostName"`
|
||||||
|
HostPorts []int `json:"hostPorts"`
|
||||||
|
IPAddresses []IPAddress `json:"ipAddresses"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePodInstances deletes all instances of the named pod
|
||||||
|
func (r *marathonClient) DeletePodInstances(name string, instances []string) ([]*PodInstance, error) {
|
||||||
|
uri := buildPodInstancesURI(name)
|
||||||
|
var result []*PodInstance
|
||||||
|
if err := r.apiDelete(uri, instances, &result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePodInstance deletes a specific instance of a pod
|
||||||
|
func (r *marathonClient) DeletePodInstance(name, instance string) (*PodInstance, error) {
|
||||||
|
uri := fmt.Sprintf("%s/%s", buildPodInstancesURI(name), instance)
|
||||||
|
result := new(PodInstance)
|
||||||
|
if err := r.apiDelete(uri, nil, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPodInstancesURI(path string) string {
|
||||||
|
return fmt.Sprintf("%s/%s::instances", marathonAPIPods, trimRootPath(path))
|
||||||
|
}
|
89
vendor/github.com/gambol99/go-marathon/pod_instance_status.go
generated
vendored
Normal file
89
vendor/github.com/gambol99/go-marathon/pod_instance_status.go
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
// PodInstanceState is the state of a specific pod instance
|
||||||
|
type PodInstanceState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PodInstanceStatePending is when an instance is pending scheduling
|
||||||
|
PodInstanceStatePending PodInstanceState = "PENDING"
|
||||||
|
|
||||||
|
// PodInstanceStateStaging is when an instance is staged to be scheduled
|
||||||
|
PodInstanceStateStaging PodInstanceState = "STAGING"
|
||||||
|
|
||||||
|
// PodInstanceStateStable is when an instance is stably running
|
||||||
|
PodInstanceStateStable PodInstanceState = "STABLE"
|
||||||
|
|
||||||
|
// PodInstanceStateDegraded is when an instance is degraded status
|
||||||
|
PodInstanceStateDegraded PodInstanceState = "DEGRADED"
|
||||||
|
|
||||||
|
// PodInstanceStateTerminal is when an instance is terminal
|
||||||
|
PodInstanceStateTerminal PodInstanceState = "TERMINAL"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodInstanceStatus is the status of a pod instance
|
||||||
|
type PodInstanceStatus struct {
|
||||||
|
AgentHostname string `json:"agentHostname,omitempty"`
|
||||||
|
Conditions []*StatusCondition `json:"conditions,omitempty"`
|
||||||
|
Containers []*ContainerStatus `json:"containers,omitempty"`
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
LastChanged string `json:"lastChanged,omitempty"`
|
||||||
|
LastUpdated string `json:"lastUpdated,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Networks []*PodNetworkStatus `json:"networks,omitempty"`
|
||||||
|
Resources *Resources `json:"resources,omitempty"`
|
||||||
|
SpecReference string `json:"specReference,omitempty"`
|
||||||
|
Status PodInstanceState `json:"status,omitempty"`
|
||||||
|
StatusSince string `json:"statusSince,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodNetworkStatus is the networks attached to a pod instance
|
||||||
|
type PodNetworkStatus struct {
|
||||||
|
Addresses []string `json:"addresses,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatusCondition describes info about a status change
|
||||||
|
type StatusCondition struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
Reason string `json:"reason,omitempty"`
|
||||||
|
LastChanged string `json:"lastChanged,omitempty"`
|
||||||
|
LastUpdated string `json:"lastUpdated,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerStatus contains all status information for a container instance
|
||||||
|
type ContainerStatus struct {
|
||||||
|
Conditions []*StatusCondition `json:"conditions,omitempty"`
|
||||||
|
ContainerID string `json:"containerId,omitempty"`
|
||||||
|
Endpoints []*PodEndpoint `json:"endpoints,omitempty"`
|
||||||
|
LastChanged string `json:"lastChanged,omitempty"`
|
||||||
|
LastUpdated string `json:"lastUpdated,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Resources *Resources `json:"resources,omitempty"`
|
||||||
|
Status string `json:"status,omitempty"`
|
||||||
|
StatusSince string `json:"statusSince,omitempty"`
|
||||||
|
Termination *ContainerTerminationState `json:"termination,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerTerminationState describes why a container terminated
|
||||||
|
type ContainerTerminationState struct {
|
||||||
|
ExitCode int `json:"exitCode,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
100
vendor/github.com/gambol99/go-marathon/pod_marshalling.go
generated
vendored
Normal file
100
vendor/github.com/gambol99/go-marathon/pod_marshalling.go
generated
vendored
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodAlias aliases the Pod struct so that it will be marshaled/unmarshaled automatically
|
||||||
|
type PodAlias Pod
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals the given Pod JSON as expected except for environment variables and secrets.
|
||||||
|
// Environment variables are stored in the Env field. Secrets, including the environment variable part,
|
||||||
|
// are stored in the Secrets field.
|
||||||
|
func (p *Pod) UnmarshalJSON(b []byte) error {
|
||||||
|
aux := &struct {
|
||||||
|
*PodAlias
|
||||||
|
Env map[string]interface{} `json:"environment"`
|
||||||
|
Secrets map[string]TmpSecret `json:"secrets"`
|
||||||
|
}{
|
||||||
|
PodAlias: (*PodAlias)(p),
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(b, aux); err != nil {
|
||||||
|
return fmt.Errorf("malformed pod definition %v", err)
|
||||||
|
}
|
||||||
|
env := map[string]string{}
|
||||||
|
secrets := map[string]Secret{}
|
||||||
|
|
||||||
|
for envName, genericEnvValue := range aux.Env {
|
||||||
|
switch envValOrSecret := genericEnvValue.(type) {
|
||||||
|
case string:
|
||||||
|
env[envName] = envValOrSecret
|
||||||
|
case map[string]interface{}:
|
||||||
|
for secret, secretStore := range envValOrSecret {
|
||||||
|
if secStore, ok := secretStore.(string); ok && secret == "secret" {
|
||||||
|
secrets[secStore] = Secret{EnvVar: envName}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return fmt.Errorf("unexpected secret field %v of value type %T", secret, envValOrSecret[secret])
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unexpected environment variable type %T", envValOrSecret)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.Env = env
|
||||||
|
for k, v := range aux.Secrets {
|
||||||
|
tmp := secrets[k]
|
||||||
|
tmp.Source = v.Source
|
||||||
|
secrets[k] = tmp
|
||||||
|
}
|
||||||
|
p.Secrets = secrets
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON marshals the given Pod as expected except for environment variables and secrets,
|
||||||
|
// which are marshaled from specialized structs. The environment variable piece of the secrets and other
|
||||||
|
// normal environment variables are combined and marshaled to the env field. The secrets and the related
|
||||||
|
// source are marshaled into the secrets field.
|
||||||
|
func (p *Pod) MarshalJSON() ([]byte, error) {
|
||||||
|
env := make(map[string]interface{})
|
||||||
|
secrets := make(map[string]TmpSecret)
|
||||||
|
|
||||||
|
if p.Env != nil {
|
||||||
|
for k, v := range p.Env {
|
||||||
|
env[string(k)] = string(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Secrets != nil {
|
||||||
|
for k, v := range p.Secrets {
|
||||||
|
// Only add it to the root level pod environment if it's used
|
||||||
|
// Otherwise it's likely in one of the container environments
|
||||||
|
if v.EnvVar != "" {
|
||||||
|
env[v.EnvVar] = TmpEnvSecret{Secret: k}
|
||||||
|
}
|
||||||
|
secrets[k] = TmpSecret{v.Source}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aux := &struct {
|
||||||
|
*PodAlias
|
||||||
|
Env map[string]interface{} `json:"environment,omitempty"`
|
||||||
|
Secrets map[string]TmpSecret `json:"secrets,omitempty"`
|
||||||
|
}{PodAlias: (*PodAlias)(p), Env: env, Secrets: secrets}
|
||||||
|
|
||||||
|
return json.Marshal(aux)
|
||||||
|
}
|
75
vendor/github.com/gambol99/go-marathon/pod_scheduling.go
generated
vendored
Normal file
75
vendor/github.com/gambol99/go-marathon/pod_scheduling.go
generated
vendored
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
// PodBackoff describes the backoff for re-run attempts of a pod
|
||||||
|
type PodBackoff struct {
|
||||||
|
Backoff *int `json:"backoff,omitempty"`
|
||||||
|
BackoffFactor *float64 `json:"backoffFactor,omitempty"`
|
||||||
|
MaxLaunchDelay *int `json:"maxLaunchDelay,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodUpgrade describes the policy for upgrading a pod in-place
|
||||||
|
type PodUpgrade struct {
|
||||||
|
MinimumHealthCapacity *float64 `json:"minimumHealthCapacity,omitempty"`
|
||||||
|
MaximumOverCapacity *float64 `json:"maximumOverCapacity,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodPlacement supports constraining which hosts a pod is placed on
|
||||||
|
type PodPlacement struct {
|
||||||
|
Constraints *[]Constraint `json:"constraints"`
|
||||||
|
AcceptedResourceRoles []string `json:"acceptedResourceRoles,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodSchedulingPolicy is the overarching pod scheduling policy
|
||||||
|
type PodSchedulingPolicy struct {
|
||||||
|
Backoff *PodBackoff `json:"backoff,omitempty"`
|
||||||
|
Upgrade *PodUpgrade `json:"upgrade,omitempty"`
|
||||||
|
Placement *PodPlacement `json:"placement,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constraint describes the constraint for pod placement
|
||||||
|
type Constraint struct {
|
||||||
|
FieldName string `json:"fieldName"`
|
||||||
|
Operator string `json:"operator"`
|
||||||
|
Value string `json:"value,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodPlacement creates an empty PodPlacement
|
||||||
|
func NewPodPlacement() *PodPlacement {
|
||||||
|
return &PodPlacement{
|
||||||
|
Constraints: &[]Constraint{},
|
||||||
|
AcceptedResourceRoles: []string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddConstraint adds a new constraint
|
||||||
|
// constraints: the constraint definition, one constraint per array element
|
||||||
|
func (r *PodPlacement) AddConstraint(constraint Constraint) *PodPlacement {
|
||||||
|
c := *r.Constraints
|
||||||
|
c = append(c, constraint)
|
||||||
|
r.Constraints = &c
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodSchedulingPolicy creates an empty PodSchedulingPolicy
|
||||||
|
func NewPodSchedulingPolicy() *PodSchedulingPolicy {
|
||||||
|
return &PodSchedulingPolicy{
|
||||||
|
Placement: NewPodPlacement(),
|
||||||
|
}
|
||||||
|
}
|
108
vendor/github.com/gambol99/go-marathon/pod_status.go
generated
vendored
Normal file
108
vendor/github.com/gambol99/go-marathon/pod_status.go
generated
vendored
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodState defines the state of a pod
|
||||||
|
type PodState string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// PodStateDegraded is a degraded pod
|
||||||
|
PodStateDegraded PodState = "DEGRADED"
|
||||||
|
|
||||||
|
// PodStateStable is a stable pod
|
||||||
|
PodStateStable PodState = "STABLE"
|
||||||
|
|
||||||
|
// PodStateTerminal is a terminal pod
|
||||||
|
PodStateTerminal PodState = "TERMINAL"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PodStatus describes the pod status
|
||||||
|
type PodStatus struct {
|
||||||
|
ID string `json:"id,omitempty"`
|
||||||
|
Spec *Pod `json:"spec,omitempty"`
|
||||||
|
Status PodState `json:"status,omitempty"`
|
||||||
|
StatusSince string `json:"statusSince,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Instances []*PodInstanceStatus `json:"instances,omitempty"`
|
||||||
|
TerminationHistory []*PodTerminationHistory `json:"terminationHistory,omitempty"`
|
||||||
|
LastUpdated string `json:"lastUpdated,omitempty"`
|
||||||
|
LastChanged string `json:"lastChanged,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodTerminationHistory is the termination history of the pod
|
||||||
|
type PodTerminationHistory struct {
|
||||||
|
InstanceID string `json:"instanceId,omitempty"`
|
||||||
|
StartedAt string `json:"startedAt,omitempty"`
|
||||||
|
TerminatedAt string `json:"terminatedAt,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
Containers []*ContainerTerminationHistory `json:"containers,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainerTerminationHistory is the termination history of a container in a pod
|
||||||
|
type ContainerTerminationHistory struct {
|
||||||
|
ContainerID string `json:"containerId,omitempty"`
|
||||||
|
LastKnownState string `json:"lastKnownState,omitempty"`
|
||||||
|
Termination *ContainerTerminationState `json:"termination,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodStatus retrieves the pod configuration from marathon
|
||||||
|
func (r *marathonClient) PodStatus(name string) (*PodStatus, error) {
|
||||||
|
var podStatus PodStatus
|
||||||
|
|
||||||
|
if err := r.apiGet(buildPodStatusURI(name), nil, &podStatus); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &podStatus, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodStatuses retrieves all pod configuration from marathon
|
||||||
|
func (r *marathonClient) PodStatuses() ([]*PodStatus, error) {
|
||||||
|
var podStatuses []*PodStatus
|
||||||
|
|
||||||
|
if err := r.apiGet(buildPodStatusURI(""), nil, &podStatuses); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return podStatuses, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitOnPod blocks until a pod to be deployed
|
||||||
|
func (r *marathonClient) WaitOnPod(name string, timeout time.Duration) error {
|
||||||
|
return r.wait(name, timeout, r.PodIsRunning)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodIsRunning returns whether the pod is stably running
|
||||||
|
func (r *marathonClient) PodIsRunning(name string) bool {
|
||||||
|
podStatus, err := r.PodStatus(name)
|
||||||
|
if apiErr, ok := err.(*APIError); ok && apiErr.ErrCode == ErrCodeNotFound {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err == nil && podStatus.Status == PodStateStable {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildPodStatusURI(path string) string {
|
||||||
|
return fmt.Sprintf("%s/%s::status", marathonAPIPods, trimRootPath(path))
|
||||||
|
}
|
2
vendor/github.com/gambol99/go-marathon/queue.go
generated
vendored
2
vendor/github.com/gambol99/go-marathon/queue.go
generated
vendored
|
@ -32,7 +32,7 @@ type Item struct {
|
||||||
Application Application `json:"app"`
|
Application Application `json:"app"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay cotains the application postpone infomation
|
// Delay cotains the application postpone information
|
||||||
type Delay struct {
|
type Delay struct {
|
||||||
Overdue bool `json:"overdue"`
|
Overdue bool `json:"overdue"`
|
||||||
TimeLeftSeconds int `json:"timeLeftSeconds"`
|
TimeLeftSeconds int `json:"timeLeftSeconds"`
|
||||||
|
|
2
vendor/github.com/gambol99/go-marathon/residency.go
generated
vendored
2
vendor/github.com/gambol99/go-marathon/residency.go
generated
vendored
|
@ -24,7 +24,7 @@ type TaskLostBehaviorType string
|
||||||
const (
|
const (
|
||||||
// TaskLostBehaviorTypeWaitForever indicates to not take any action when the resident task is lost
|
// TaskLostBehaviorTypeWaitForever indicates to not take any action when the resident task is lost
|
||||||
TaskLostBehaviorTypeWaitForever TaskLostBehaviorType = "WAIT_FOREVER"
|
TaskLostBehaviorTypeWaitForever TaskLostBehaviorType = "WAIT_FOREVER"
|
||||||
// TaskLostBehaviorTypeWaitForever indicates to try relaunching the lost resident task on
|
// TaskLostBehaviorTypeRelaunchAfterTimeout indicates to try relaunching the lost resident task on
|
||||||
// another node after the relaunch escalation timeout has elapsed
|
// another node after the relaunch escalation timeout has elapsed
|
||||||
TaskLostBehaviorTypeRelaunchAfterTimeout TaskLostBehaviorType = "RELAUNCH_AFTER_TIMEOUT"
|
TaskLostBehaviorTypeRelaunchAfterTimeout TaskLostBehaviorType = "RELAUNCH_AFTER_TIMEOUT"
|
||||||
)
|
)
|
||||||
|
|
37
vendor/github.com/gambol99/go-marathon/resources.go
generated
vendored
Normal file
37
vendor/github.com/gambol99/go-marathon/resources.go
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
// ExecutorResources are the resources supported by an executor (a task running a pod)
|
||||||
|
type ExecutorResources struct {
|
||||||
|
Cpus float64 `json:"cpus,omitempty"`
|
||||||
|
Mem float64 `json:"mem,omitempty"`
|
||||||
|
Disk float64 `json:"disk,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resources are the full set of resources for a task
|
||||||
|
type Resources struct {
|
||||||
|
Cpus float64 `json:"cpus"`
|
||||||
|
Mem float64 `json:"mem"`
|
||||||
|
Disk float64 `json:"disk,omitempty"`
|
||||||
|
Gpus int32 `json:"gpus,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewResources creates an empty Resources
|
||||||
|
func NewResources() *Resources {
|
||||||
|
return &Resources{}
|
||||||
|
}
|
2
vendor/github.com/gambol99/go-marathon/subscription.go
generated
vendored
2
vendor/github.com/gambol99/go-marathon/subscription.go
generated
vendored
|
@ -162,7 +162,7 @@ func (r *marathonClient) registerCallbackSubscription() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerSSESubscription starts a go routine that continously tries to
|
// registerSSESubscription starts a go routine that continuously tries to
|
||||||
// connect to the SSE stream and to process the received events. To establish
|
// connect to the SSE stream and to process the received events. To establish
|
||||||
// the connection it tries the active cluster members until no more member is
|
// the connection it tries the active cluster members until no more member is
|
||||||
// active. When this happens it will retry to get a connection every 5 seconds.
|
// active. When this happens it will retry to get a connection every 5 seconds.
|
||||||
|
|
3
vendor/github.com/gambol99/go-marathon/task.go
generated
vendored
3
vendor/github.com/gambol99/go-marathon/task.go
generated
vendored
|
@ -185,9 +185,12 @@ func (r *marathonClient) TaskEndpoints(name string, port int, healthCheck bool)
|
||||||
|
|
||||||
// step: we need to get the port index of the service we are interested in
|
// step: we need to get the port index of the service we are interested in
|
||||||
portIndex, err := application.Container.Docker.ServicePortIndex(port)
|
portIndex, err := application.Container.Docker.ServicePortIndex(port)
|
||||||
|
if err != nil {
|
||||||
|
portIndex, err = application.Container.ServicePortIndex(port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// step: do we have any tasks?
|
// step: do we have any tasks?
|
||||||
if application.Tasks == nil || len(application.Tasks) == 0 {
|
if application.Tasks == nil || len(application.Tasks) == 0 {
|
||||||
|
|
1
vendor/github.com/gambol99/go-marathon/unreachable_strategy.go
generated
vendored
1
vendor/github.com/gambol99/go-marathon/unreachable_strategy.go
generated
vendored
|
@ -21,6 +21,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UnreachableStrategyAbsenceReasonDisabled signifies the reason of disabled unreachable strategy
|
||||||
const UnreachableStrategyAbsenceReasonDisabled = "disabled"
|
const UnreachableStrategyAbsenceReasonDisabled = "disabled"
|
||||||
|
|
||||||
// UnreachableStrategy is the unreachable strategy applied to an application.
|
// UnreachableStrategy is the unreachable strategy applied to an application.
|
||||||
|
|
45
vendor/github.com/gambol99/go-marathon/volume.go
generated
vendored
Normal file
45
vendor/github.com/gambol99/go-marathon/volume.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The go-marathon Authors 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
|
||||||
|
|
||||||
|
// PodVolume describes a volume on the host
|
||||||
|
type PodVolume struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Host string `json:"host,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PodVolumeMount describes how to mount a volume into a task
|
||||||
|
type PodVolumeMount struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
MountPath string `json:"mountPath,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodVolume creates a new PodVolume
|
||||||
|
func NewPodVolume(name, path string) *PodVolume {
|
||||||
|
return &PodVolume{
|
||||||
|
Name: name,
|
||||||
|
Host: path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPodVolumeMount creates a new PodVolumeMount
|
||||||
|
func NewPodVolumeMount(name, mount string) *PodVolumeMount {
|
||||||
|
return &PodVolumeMount{
|
||||||
|
Name: name,
|
||||||
|
MountPath: mount,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue