diff --git a/rancher/service.go b/rancher/service.go index 902b627f..dd0fa47c 100644 --- a/rancher/service.go +++ b/rancher/service.go @@ -164,11 +164,41 @@ func (r *RancherService) Delete() error { return r.Wait(service) } +func (r *RancherService) resolveServiceAndEnvironmentId(name string) (string, string, error) { + parts := strings.SplitN(name, "/", 2) + if len(parts) == 1 { + return name, r.context.Environment.Id, nil + } + + envs, err := r.context.Client.Environment.List(&rancherClient.ListOpts{ + Filters: map[string]interface{}{ + "name": parts[0], + "removed_null": nil, + }, + }) + + if err != nil { + return "", "", err + } + + if len(envs.Data) == 0 { + return "", "", fmt.Errorf("Failed to find environment: %s", parts[0]) + } + + return parts[1], envs.Data[0].Id, nil +} + func (r *RancherService) findExisting(name string) (*rancherClient.Service, error) { logrus.Debugf("Finding service %s", name) + + name, environmentId, err := r.resolveServiceAndEnvironmentId(name) + if err != nil { + return nil, err + } + services, err := r.context.Client.Service.List(&rancherClient.ListOpts{ Filters: map[string]interface{}{ - "environmentId": r.context.Environment.Id, + "environmentId": environmentId, "name": name, "removed_null": nil, }, @@ -418,7 +448,7 @@ func (r *RancherService) getServiceLinks() ([]interface{}, error) { func (r *RancherService) getLinks() (map[Link]string, error) { result := map[Link]string{} - for _, link := range r.serviceConfig.Links.Slice() { + for _, link := range append(r.serviceConfig.Links.Slice(), r.serviceConfig.ExternalLinks...) { parts := strings.SplitN(link, ":", 2) name := parts[0] alias := name @@ -581,9 +611,9 @@ func (r *RancherService) Scale(count int) error { return fmt.Errorf("Failed to find %s to scale", r.name) } - service.Scale = int64(count) - - service, err = r.context.Client.Service.Update(service, service) + service, err = r.context.Client.Service.Update(service, map[string]interface{}{ + "scale": count, + }) if err != nil { return err } diff --git a/scripts/run-cattle b/scripts/run-cattle index d83596fc..100ee4fc 100755 --- a/scripts/run-cattle +++ b/scripts/run-cattle @@ -1,7 +1,7 @@ #!/bin/bash set -e -URL=https://github.com/rancherio/cattle/releases/download/v0.66.0/cattle.jar +URL=https://github.com/rancherio/cattle/releases/download/v0.69.0/cattle.jar cd $(dirname $0)/.. diff --git a/tests/integration/cattletest/core/assets/full.yml b/tests/integration/cattletest/core/assets/full.yml index 0f4e2e6e..28b2eced 100644 --- a/tests/integration/cattletest/core/assets/full.yml +++ b/tests/integration/cattletest/core/assets/full.yml @@ -58,3 +58,6 @@ web: - "label:foo" - "label:bar" volume_driver: foo + external_links: + - foo + - bar diff --git a/tests/integration/cattletest/core/assets/upgrade-ignore-scale/docker-compose-source.yml b/tests/integration/cattletest/core/assets/upgrade-ignore-scale/docker-compose-source.yml new file mode 100644 index 00000000..97a3677b --- /dev/null +++ b/tests/integration/cattletest/core/assets/upgrade-ignore-scale/docker-compose-source.yml @@ -0,0 +1,2 @@ +from: + image: nginx diff --git a/tests/integration/cattletest/core/assets/upgrade-ignore-scale/docker-compose.yml b/tests/integration/cattletest/core/assets/upgrade-ignore-scale/docker-compose.yml new file mode 100644 index 00000000..05a84880 --- /dev/null +++ b/tests/integration/cattletest/core/assets/upgrade-ignore-scale/docker-compose.yml @@ -0,0 +1,4 @@ +from: + image: nginx +to: + image: nginx diff --git a/tests/integration/cattletest/core/assets/upgrade-ignore-scale/rancher-compose.yml b/tests/integration/cattletest/core/assets/upgrade-ignore-scale/rancher-compose.yml new file mode 100644 index 00000000..cc18a266 --- /dev/null +++ b/tests/integration/cattletest/core/assets/upgrade-ignore-scale/rancher-compose.yml @@ -0,0 +1,2 @@ +to: + scale: 100 diff --git a/tests/integration/cattletest/core/test_compose.py b/tests/integration/cattletest/core/test_compose.py index 26573495..a96d9668 100644 --- a/tests/integration/cattletest/core/test_compose.py +++ b/tests/integration/cattletest/core/test_compose.py @@ -19,6 +19,13 @@ def __init__(self, client, compose_bin): self.compose_bin = compose_bin self.client = client + def check_retcode(self, input, check_retcode, *args): + p = self.call(*args) + p.communicate(input=input) + retcode = p.wait() + assert check_retcode == retcode + return p + def check_call(self, input, *args): p = self.call(*args) p.communicate(input=input) @@ -165,6 +172,8 @@ def test_args(client, compose): 'dockerfile': 'something/other', 'remote': 'github.com/ibuildthecloud/tiny-build', } + # Not supported + # assert service.launchConfig.externalLinks == ['foo', 'bar'] def test_git_build(client, compose): @@ -378,8 +387,13 @@ def test_extends_1556(client, compose): project = find_one(client.list_environment, name=project_name) assert project.name == project_name + web = _get_service(project.services(), 'web') db = _get_service(project.services(), 'db') + # Notice the images are wrong + assert web.launchConfig.imageUuid == 'docker:ubuntu:14:04' + assert db.launchConfig.imageUuid == 'docker:ubuntu:14:04' + web = find_one(db.consumedservices) assert web.name == 'web' @@ -891,6 +905,29 @@ def check(): assert consumed[0].name == 'web2' +def test_service_upgrade_from_nil(client, compose): + template = ''' + foo: + image: nginx + web2: + image: nginx + ''' + + project_name = create_project(compose, input=template) + + upgrade = ''' + foo: + image: nginx + web: + image: nginx + web2: + image: nginx + ''' + + compose.check_retcode(upgrade, 1, '-p', project_name, '-f', + '-', 'upgrade', 'web', 'web2') + + def test_service_map_syntax(client, compose): template = ''' foo: @@ -910,6 +947,56 @@ def test_service_map_syntax(client, compose): assert maps[0].name == 'alias' +def test_cross_stack_link(client, compose): + template = ''' + dest: + image: nginx + ''' + + project_name = create_project(compose, input=template) + project = find_one(client.list_environment, name=project_name) + dest = _get_service(project.services(), 'dest') + + template = ''' + src: + external_links: + - {}/dest + image: nginx + '''.format(project_name) + + project_name = create_project(compose, input=template) + project = find_one(client.list_environment, name=project_name) + src = _get_service(project.services(), 'src') + + services = src.consumedservices() + assert len(services) == 1 + + assert services[0].id == dest.id + + +def test_upgrade_ignore_scale(client, compose): + project_name = create_project(compose, file='assets/upgrade-ignore-scale/' + 'docker-compose-source.yml') + compose.check_call(None, '--verbose', '-f', 'assets/upgrade-ignore-scale/' + 'docker-compose-source.yml', + '-p', project_name, 'up', '-d') + project = find_one(client.list_environment, name=project_name) + compose.check_call(None, '-p', project_name, '-f', + 'assets/upgrade-ignore-scale/docker-compose.yml', + 'upgrade', '--scale=2', 'from', 'to') + + f = _get_service(project.services(), 'from') + to = _get_service(project.services(), 'to') + + assert to.scale == 0 + + f = client.wait_success(f) + to = client.wait_success(to) + + assert f.scale == 0 + assert to.scale == 2 + + def test_service_link_with_space(client, compose): template = ''' foo: diff --git a/upgrade/upgrade.go b/upgrade/upgrade.go index d67de217..3f6ebbfc 100644 --- a/upgrade/upgrade.go +++ b/upgrade/upgrade.go @@ -38,7 +38,11 @@ func Upgrade(p *project.Project, from, to string, opts UpgradeOpts) error { return fmt.Errorf("%s is not a Rancher service", to) } - if err := rToService.Up(); err != nil { + if err := rToService.Create(); err != nil { + return err + } + + if err := rToService.Scale(0); err != nil { return err } @@ -52,6 +56,14 @@ func Upgrade(p *project.Project, from, to string, opts UpgradeOpts) error { return err } + if source == nil { + return fmt.Errorf("Failed to find service %s", from) + } + + if dest == nil { + return fmt.Errorf("Failed to find service %s", to) + } + upgradeOpts := &rancherClient.ServiceUpgrade{ UpdateLinks: opts.UpdateLinks, FinalScale: int64(opts.FinalScale),