diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 56102c98..434613bd 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -22,11 +22,6 @@ "Comment": "v1.3.2-6-g405c260", "Rev": "405c2600b19ae77516c967f8ee8ebde5624d3663" }, - { - "ImportPath": "github.com/coreos/coreos-cloudinit/initialize", - "Comment": "v1.3.2-6-g405c260", - "Rev": "405c2600b19ae77516c967f8ee8ebde5624d3663" - }, { "ImportPath": "github.com/coreos/coreos-cloudinit/network", "Comment": "v1.3.2-6-g405c260", @@ -226,13 +221,13 @@ }, { "ImportPath": "github.com/rancherio/rancher-compose/docker", - "Comment": "0.1.0-8-g45c7de3", - "Rev": "45c7de3d9b5b106475cf1461df7550bdaab0a9aa" + "Comment": "0.1.0-9-g7343438", + "Rev": "734343806223cab5de0532ea7add0beeb2cbea92" }, { "ImportPath": "github.com/rancherio/rancher-compose/project", - "Comment": "0.1.0-8-g45c7de3", - "Rev": "45c7de3d9b5b106475cf1461df7550bdaab0a9aa" + "Comment": "0.1.0-9-g7343438", + "Rev": "734343806223cab5de0532ea7add0beeb2cbea92" }, { "ImportPath": "github.com/ryanuber/go-glob", diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/config.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/config.go deleted file mode 100644 index 3bf7f541..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/config.go +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "errors" - "fmt" - "log" - "path" - - "github.com/coreos/coreos-cloudinit/config" - "github.com/coreos/coreos-cloudinit/network" - "github.com/coreos/coreos-cloudinit/system" -) - -// CloudConfigFile represents a CoreOS specific configuration option that can generate -// an associated system.File to be written to disk -type CloudConfigFile interface { - // File should either return (*system.File, error), or (nil, nil) if nothing - // needs to be done for this configuration option. - File() (*system.File, error) -} - -// CloudConfigUnit represents a CoreOS specific configuration option that can generate -// associated system.Units to be created/enabled appropriately -type CloudConfigUnit interface { - Units() []system.Unit -} - -// Apply renders a CloudConfig to an Environment. This can involve things like -// configuring the hostname, adding new users, writing various configuration -// files to disk, and manipulating systemd services. -func Apply(cfg config.CloudConfig, ifaces []network.InterfaceGenerator, env *Environment) error { - if cfg.Hostname != "" { - if err := system.SetHostname(cfg.Hostname); err != nil { - return err - } - log.Printf("Set hostname to %s", cfg.Hostname) - } - - for _, user := range cfg.Users { - if user.Name == "" { - log.Printf("User object has no 'name' field, skipping") - continue - } - - if system.UserExists(&user) { - log.Printf("User '%s' exists, ignoring creation-time fields", user.Name) - if user.PasswordHash != "" { - log.Printf("Setting '%s' user's password", user.Name) - if err := system.SetUserPassword(user.Name, user.PasswordHash); err != nil { - log.Printf("Failed setting '%s' user's password: %v", user.Name, err) - return err - } - } - } else { - log.Printf("Creating user '%s'", user.Name) - if err := system.CreateUser(&user); err != nil { - log.Printf("Failed creating user '%s': %v", user.Name, err) - return err - } - } - - if len(user.SSHAuthorizedKeys) > 0 { - log.Printf("Authorizing %d SSH keys for user '%s'", len(user.SSHAuthorizedKeys), user.Name) - if err := system.AuthorizeSSHKeys(user.Name, env.SSHKeyName(), user.SSHAuthorizedKeys); err != nil { - return err - } - } - if user.SSHImportGithubUser != "" { - log.Printf("Authorizing github user %s SSH keys for CoreOS user '%s'", user.SSHImportGithubUser, user.Name) - if err := SSHImportGithubUser(user.Name, user.SSHImportGithubUser); err != nil { - return err - } - } - for _, u := range user.SSHImportGithubUsers { - log.Printf("Authorizing github user %s SSH keys for CoreOS user '%s'", u, user.Name) - if err := SSHImportGithubUser(user.Name, u); err != nil { - return err - } - } - if user.SSHImportURL != "" { - log.Printf("Authorizing SSH keys for CoreOS user '%s' from '%s'", user.Name, user.SSHImportURL) - if err := SSHImportKeysFromURL(user.Name, user.SSHImportURL); err != nil { - return err - } - } - } - - if len(cfg.SSHAuthorizedKeys) > 0 { - err := system.AuthorizeSSHKeys("core", env.SSHKeyName(), cfg.SSHAuthorizedKeys) - if err == nil { - log.Printf("Authorized SSH keys for core user") - } else { - return err - } - } - - var writeFiles []system.File - for _, file := range cfg.WriteFiles { - writeFiles = append(writeFiles, system.File{File: file}) - } - - for _, ccf := range []CloudConfigFile{ - system.OEM{OEM: cfg.CoreOS.OEM}, - system.Update{Update: cfg.CoreOS.Update, ReadConfig: system.DefaultReadConfig}, - system.EtcHosts{EtcHosts: cfg.ManageEtcHosts}, - system.Flannel{Flannel: cfg.CoreOS.Flannel}, - } { - f, err := ccf.File() - if err != nil { - return err - } - if f != nil { - writeFiles = append(writeFiles, *f) - } - } - - var units []system.Unit - for _, u := range cfg.CoreOS.Units { - units = append(units, system.Unit{Unit: u}) - } - - for _, ccu := range []CloudConfigUnit{ - system.Etcd{Etcd: cfg.CoreOS.Etcd}, - system.Fleet{Fleet: cfg.CoreOS.Fleet}, - system.Locksmith{Locksmith: cfg.CoreOS.Locksmith}, - system.Update{Update: cfg.CoreOS.Update, ReadConfig: system.DefaultReadConfig}, - } { - units = append(units, ccu.Units()...) - } - - wroteEnvironment := false - for _, file := range writeFiles { - fullPath, err := system.WriteFile(&file, env.Root()) - if err != nil { - return err - } - if path.Clean(file.Path) == "/etc/environment" { - wroteEnvironment = true - } - log.Printf("Wrote file %s to filesystem", fullPath) - } - - if !wroteEnvironment { - ef := env.DefaultEnvironmentFile() - if ef != nil { - err := system.WriteEnvFile(ef, env.Root()) - if err != nil { - return err - } - log.Printf("Updated /etc/environment") - } - } - - if len(ifaces) > 0 { - units = append(units, createNetworkingUnits(ifaces)...) - if err := system.RestartNetwork(ifaces); err != nil { - return err - } - } - - um := system.NewUnitManager(env.Root()) - return processUnits(units, env.Root(), um) -} - -func createNetworkingUnits(interfaces []network.InterfaceGenerator) (units []system.Unit) { - appendNewUnit := func(units []system.Unit, name, content string) []system.Unit { - if content == "" { - return units - } - return append(units, system.Unit{Unit: config.Unit{ - Name: name, - Runtime: true, - Content: content, - }}) - } - for _, i := range interfaces { - units = appendNewUnit(units, fmt.Sprintf("%s.netdev", i.Filename()), i.Netdev()) - units = appendNewUnit(units, fmt.Sprintf("%s.link", i.Filename()), i.Link()) - units = appendNewUnit(units, fmt.Sprintf("%s.network", i.Filename()), i.Network()) - } - return units -} - -// processUnits takes a set of Units and applies them to the given root using -// the given UnitManager. This can involve things like writing unit files to -// disk, masking/unmasking units, or invoking systemd -// commands against units. It returns any error encountered. -func processUnits(units []system.Unit, root string, um system.UnitManager) error { - type action struct { - unit system.Unit - command string - } - actions := make([]action, 0, len(units)) - reload := false - restartNetworkd := false - for _, unit := range units { - if unit.Name == "" { - log.Printf("Skipping unit without name") - continue - } - - if unit.Content != "" { - log.Printf("Writing unit %q to filesystem", unit.Name) - if err := um.PlaceUnit(unit); err != nil { - return err - } - log.Printf("Wrote unit %q", unit.Name) - reload = true - } - - for _, dropin := range unit.DropIns { - if dropin.Name != "" && dropin.Content != "" { - log.Printf("Writing drop-in unit %q to filesystem", dropin.Name) - if err := um.PlaceUnitDropIn(unit, dropin); err != nil { - return err - } - log.Printf("Wrote drop-in unit %q", dropin.Name) - reload = true - } - } - - if unit.Mask { - log.Printf("Masking unit file %q", unit.Name) - if err := um.MaskUnit(unit); err != nil { - return err - } - } else if unit.Runtime { - log.Printf("Ensuring runtime unit file %q is unmasked", unit.Name) - if err := um.UnmaskUnit(unit); err != nil { - return err - } - } - - if unit.Enable { - if unit.Group() != "network" { - log.Printf("Enabling unit file %q", unit.Name) - if err := um.EnableUnitFile(unit); err != nil { - return err - } - log.Printf("Enabled unit %q", unit.Name) - } else { - log.Printf("Skipping enable for network-like unit %q", unit.Name) - } - } - - if unit.Group() == "network" { - restartNetworkd = true - } else if unit.Command != "" { - actions = append(actions, action{unit, unit.Command}) - } - } - - if reload { - if err := um.DaemonReload(); err != nil { - return errors.New(fmt.Sprintf("failed systemd daemon-reload: %s", err)) - } - } - - if restartNetworkd { - log.Printf("Restarting systemd-networkd") - networkd := system.Unit{Unit: config.Unit{Name: "systemd-networkd.service"}} - res, err := um.RunUnitCommand(networkd, "restart") - if err != nil { - return err - } - log.Printf("Restarted systemd-networkd (%s)", res) - } - - for _, action := range actions { - log.Printf("Calling unit command %q on %q'", action.command, action.unit.Name) - res, err := um.RunUnitCommand(action.unit, action.command) - if err != nil { - return err - } - log.Printf("Result of %q on %q: %s", action.command, action.unit.Name, res) - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/config_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/config_test.go deleted file mode 100644 index 33be737e..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/config_test.go +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/config" - "github.com/coreos/coreos-cloudinit/network" - "github.com/coreos/coreos-cloudinit/system" -) - -type TestUnitManager struct { - placed []string - enabled []string - masked []string - unmasked []string - commands []UnitAction - reload bool -} - -type UnitAction struct { - unit string - command string -} - -func (tum *TestUnitManager) PlaceUnit(u system.Unit) error { - tum.placed = append(tum.placed, u.Name) - return nil -} -func (tum *TestUnitManager) PlaceUnitDropIn(u system.Unit, d config.UnitDropIn) error { - tum.placed = append(tum.placed, u.Name+".d/"+d.Name) - return nil -} -func (tum *TestUnitManager) EnableUnitFile(u system.Unit) error { - tum.enabled = append(tum.enabled, u.Name) - return nil -} -func (tum *TestUnitManager) RunUnitCommand(u system.Unit, c string) (string, error) { - tum.commands = append(tum.commands, UnitAction{u.Name, c}) - return "", nil -} -func (tum *TestUnitManager) DaemonReload() error { - tum.reload = true - return nil -} -func (tum *TestUnitManager) MaskUnit(u system.Unit) error { - tum.masked = append(tum.masked, u.Name) - return nil -} -func (tum *TestUnitManager) UnmaskUnit(u system.Unit) error { - tum.unmasked = append(tum.unmasked, u.Name) - return nil -} - -type mockInterface struct { - name string - filename string - netdev string - link string - network string - kind string - modprobeParams string -} - -func (i mockInterface) Name() string { - return i.name -} - -func (i mockInterface) Filename() string { - return i.filename -} - -func (i mockInterface) Netdev() string { - return i.netdev -} - -func (i mockInterface) Link() string { - return i.link -} - -func (i mockInterface) Network() string { - return i.network -} - -func (i mockInterface) Type() string { - return i.kind -} - -func (i mockInterface) ModprobeParams() string { - return i.modprobeParams -} - -func TestCreateNetworkingUnits(t *testing.T) { - for _, tt := range []struct { - interfaces []network.InterfaceGenerator - expect []system.Unit - }{ - {nil, nil}, - { - []network.InterfaceGenerator{ - network.InterfaceGenerator(mockInterface{filename: "test"}), - }, - nil, - }, - { - []network.InterfaceGenerator{ - network.InterfaceGenerator(mockInterface{filename: "test1", netdev: "test netdev"}), - network.InterfaceGenerator(mockInterface{filename: "test2", link: "test link"}), - network.InterfaceGenerator(mockInterface{filename: "test3", network: "test network"}), - }, - []system.Unit{ - system.Unit{Unit: config.Unit{Name: "test1.netdev", Runtime: true, Content: "test netdev"}}, - system.Unit{Unit: config.Unit{Name: "test2.link", Runtime: true, Content: "test link"}}, - system.Unit{Unit: config.Unit{Name: "test3.network", Runtime: true, Content: "test network"}}, - }, - }, - { - []network.InterfaceGenerator{ - network.InterfaceGenerator(mockInterface{filename: "test", netdev: "test netdev", link: "test link", network: "test network"}), - }, - []system.Unit{ - system.Unit{Unit: config.Unit{Name: "test.netdev", Runtime: true, Content: "test netdev"}}, - system.Unit{Unit: config.Unit{Name: "test.link", Runtime: true, Content: "test link"}}, - system.Unit{Unit: config.Unit{Name: "test.network", Runtime: true, Content: "test network"}}, - }, - }, - } { - units := createNetworkingUnits(tt.interfaces) - if !reflect.DeepEqual(tt.expect, units) { - t.Errorf("bad units (%+v): want %#v, got %#v", tt.interfaces, tt.expect, units) - } - } -} - -func TestProcessUnits(t *testing.T) { - tests := []struct { - units []system.Unit - - result TestUnitManager - }{ - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "foo", - Mask: true, - }}, - }, - result: TestUnitManager{ - masked: []string{"foo"}, - }, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "baz.service", - Content: "[Service]\nExecStart=/bin/baz", - Command: "start", - }}, - system.Unit{Unit: config.Unit{ - Name: "foo.network", - Content: "[Network]\nFoo=true", - }}, - system.Unit{Unit: config.Unit{ - Name: "bar.network", - Content: "[Network]\nBar=true", - }}, - }, - result: TestUnitManager{ - placed: []string{"baz.service", "foo.network", "bar.network"}, - commands: []UnitAction{ - UnitAction{"systemd-networkd.service", "restart"}, - UnitAction{"baz.service", "start"}, - }, - reload: true, - }, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "baz.service", - Content: "[Service]\nExecStart=/bin/true", - }}, - }, - result: TestUnitManager{ - placed: []string{"baz.service"}, - reload: true, - }, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "locksmithd.service", - Runtime: true, - }}, - }, - result: TestUnitManager{ - unmasked: []string{"locksmithd.service"}, - }, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "woof", - Enable: true, - }}, - }, - result: TestUnitManager{ - enabled: []string{"woof"}, - }, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "hi.service", - Runtime: true, - Content: "[Service]\nExecStart=/bin/echo hi", - DropIns: []config.UnitDropIn{ - { - Name: "lo.conf", - Content: "[Service]\nExecStart=/bin/echo lo", - }, - { - Name: "bye.conf", - Content: "[Service]\nExecStart=/bin/echo bye", - }, - }, - }}, - }, - result: TestUnitManager{ - placed: []string{"hi.service", "hi.service.d/lo.conf", "hi.service.d/bye.conf"}, - unmasked: []string{"hi.service"}, - reload: true, - }, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - DropIns: []config.UnitDropIn{ - { - Name: "lo.conf", - Content: "[Service]\nExecStart=/bin/echo lo", - }, - }, - }}, - }, - result: TestUnitManager{}, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "hi.service", - DropIns: []config.UnitDropIn{ - { - Content: "[Service]\nExecStart=/bin/echo lo", - }, - }, - }}, - }, - result: TestUnitManager{}, - }, - { - units: []system.Unit{ - system.Unit{Unit: config.Unit{ - Name: "hi.service", - DropIns: []config.UnitDropIn{ - { - Name: "lo.conf", - }, - }, - }}, - }, - result: TestUnitManager{}, - }, - } - - for _, tt := range tests { - tum := &TestUnitManager{} - if err := processUnits(tt.units, "", tum); err != nil { - t.Errorf("bad error (%+v): want nil, got %s", tt.units, err) - } - if !reflect.DeepEqual(tt.result, *tum) { - t.Errorf("bad result (%+v): want %+v, got %+v", tt.units, tt.result, tum) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/env.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/env.go deleted file mode 100644 index f90cc932..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/env.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "net" - "os" - "path" - "regexp" - "strings" - - "github.com/coreos/coreos-cloudinit/config" - "github.com/coreos/coreos-cloudinit/datasource" - "github.com/coreos/coreos-cloudinit/system" -) - -const DefaultSSHKeyName = "coreos-cloudinit" - -type Environment struct { - root string - configRoot string - workspace string - sshKeyName string - substitutions map[string]string -} - -// TODO(jonboulle): this is getting unwieldy, should be able to simplify the interface somehow -func NewEnvironment(root, configRoot, workspace, sshKeyName string, metadata datasource.Metadata) *Environment { - firstNonNull := func(ip net.IP, env string) string { - if ip == nil { - return env - } - return ip.String() - } - substitutions := map[string]string{ - "$public_ipv4": firstNonNull(metadata.PublicIPv4, os.Getenv("COREOS_PUBLIC_IPV4")), - "$private_ipv4": firstNonNull(metadata.PrivateIPv4, os.Getenv("COREOS_PRIVATE_IPV4")), - "$public_ipv6": firstNonNull(metadata.PublicIPv6, os.Getenv("COREOS_PUBLIC_IPV6")), - "$private_ipv6": firstNonNull(metadata.PrivateIPv6, os.Getenv("COREOS_PRIVATE_IPV6")), - } - return &Environment{root, configRoot, workspace, sshKeyName, substitutions} -} - -func (e *Environment) Workspace() string { - return path.Join(e.root, e.workspace) -} - -func (e *Environment) Root() string { - return e.root -} - -func (e *Environment) ConfigRoot() string { - return e.configRoot -} - -func (e *Environment) SSHKeyName() string { - return e.sshKeyName -} - -func (e *Environment) SetSSHKeyName(name string) { - e.sshKeyName = name -} - -// Apply goes through the map of substitutions and replaces all instances of -// the keys with their respective values. It supports escaping substitutions -// with a leading '\'. -func (e *Environment) Apply(data string) string { - for key, val := range e.substitutions { - matchKey := strings.Replace(key, `$`, `\$`, -1) - replKey := strings.Replace(key, `$`, `$$`, -1) - - // "key" -> "val" - data = regexp.MustCompile(`([^\\]|^)`+matchKey).ReplaceAllString(data, `${1}`+val) - // "\key" -> "key" - data = regexp.MustCompile(`\\`+matchKey).ReplaceAllString(data, replKey) - } - return data -} - -func (e *Environment) DefaultEnvironmentFile() *system.EnvFile { - ef := system.EnvFile{ - File: &system.File{File: config.File{ - Path: "/etc/environment", - }}, - Vars: map[string]string{}, - } - if ip, ok := e.substitutions["$public_ipv4"]; ok && len(ip) > 0 { - ef.Vars["COREOS_PUBLIC_IPV4"] = ip - } - if ip, ok := e.substitutions["$private_ipv4"]; ok && len(ip) > 0 { - ef.Vars["COREOS_PRIVATE_IPV4"] = ip - } - if ip, ok := e.substitutions["$public_ipv6"]; ok && len(ip) > 0 { - ef.Vars["COREOS_PUBLIC_IPV6"] = ip - } - if ip, ok := e.substitutions["$private_ipv6"]; ok && len(ip) > 0 { - ef.Vars["COREOS_PRIVATE_IPV6"] = ip - } - if len(ef.Vars) == 0 { - return nil - } else { - return &ef - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/env_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/env_test.go deleted file mode 100644 index abb770cf..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/env_test.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "io/ioutil" - "net" - "os" - "path" - "testing" - - "github.com/coreos/coreos-cloudinit/datasource" - "github.com/coreos/coreos-cloudinit/system" -) - -func TestEnvironmentApply(t *testing.T) { - os.Setenv("COREOS_PUBLIC_IPV4", "1.2.3.4") - os.Setenv("COREOS_PRIVATE_IPV4", "5.6.7.8") - os.Setenv("COREOS_PUBLIC_IPV6", "1234::") - os.Setenv("COREOS_PRIVATE_IPV6", "5678::") - for _, tt := range []struct { - metadata datasource.Metadata - input string - out string - }{ - { - // Substituting both values directly should always take precedence - // over environment variables - datasource.Metadata{ - PublicIPv4: net.ParseIP("192.0.2.3"), - PrivateIPv4: net.ParseIP("192.0.2.203"), - PublicIPv6: net.ParseIP("fe00:1234::"), - PrivateIPv6: net.ParseIP("fe00:5678::"), - }, - `[Service] -ExecStart=/usr/bin/echo "$public_ipv4 $public_ipv6" -ExecStop=/usr/bin/echo $private_ipv4 $private_ipv6 -ExecStop=/usr/bin/echo $unknown`, - `[Service] -ExecStart=/usr/bin/echo "192.0.2.3 fe00:1234::" -ExecStop=/usr/bin/echo 192.0.2.203 fe00:5678:: -ExecStop=/usr/bin/echo $unknown`, - }, - { - // Substituting one value directly while falling back with the other - datasource.Metadata{ - PrivateIPv4: net.ParseIP("127.0.0.1"), - }, - "$private_ipv4\n$public_ipv4", - "127.0.0.1\n1.2.3.4", - }, - { - // Falling back to environment variables for both values - datasource.Metadata{}, - "$private_ipv4\n$public_ipv4", - "5.6.7.8\n1.2.3.4", - }, - { - // No substitutions - datasource.Metadata{}, - "$private_ipv4\nfoobar", - "5.6.7.8\nfoobar", - }, - { - // Escaping substitutions - datasource.Metadata{ - PrivateIPv4: net.ParseIP("127.0.0.1"), - }, - `\$private_ipv4 -$private_ipv4 -addr: \$private_ipv4 -\\$private_ipv4`, - `$private_ipv4 -127.0.0.1 -addr: $private_ipv4 -\$private_ipv4`, - }, - { - // No substitutions with escaping - datasource.Metadata{}, - "\\$test\n$test", - "\\$test\n$test", - }, - } { - - env := NewEnvironment("./", "./", "./", "", tt.metadata) - got := env.Apply(tt.input) - if got != tt.out { - t.Fatalf("Environment incorrectly applied.\ngot:\n%s\nwant:\n%s", got, tt.out) - } - } -} - -func TestEnvironmentFile(t *testing.T) { - metadata := datasource.Metadata{ - PublicIPv4: net.ParseIP("1.2.3.4"), - PrivateIPv4: net.ParseIP("5.6.7.8"), - PublicIPv6: net.ParseIP("1234::"), - PrivateIPv6: net.ParseIP("5678::"), - } - expect := "COREOS_PRIVATE_IPV4=5.6.7.8\nCOREOS_PRIVATE_IPV6=5678::\nCOREOS_PUBLIC_IPV4=1.2.3.4\nCOREOS_PUBLIC_IPV6=1234::\n" - - dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-") - if err != nil { - t.Fatalf("Unable to create tempdir: %v", err) - } - defer os.RemoveAll(dir) - - env := NewEnvironment("./", "./", "./", "", metadata) - ef := env.DefaultEnvironmentFile() - err = system.WriteEnvFile(ef, dir) - if err != nil { - t.Fatalf("WriteEnvFile failed: %v", err) - } - - fullPath := path.Join(dir, "etc", "environment") - contents, err := ioutil.ReadFile(fullPath) - if err != nil { - t.Fatalf("Unable to read expected file: %v", err) - } - - if string(contents) != expect { - t.Fatalf("File has incorrect contents: %q", contents) - } -} - -func TestEnvironmentFileNil(t *testing.T) { - os.Clearenv() - metadata := datasource.Metadata{} - - env := NewEnvironment("./", "./", "./", "", metadata) - ef := env.DefaultEnvironmentFile() - if ef != nil { - t.Fatalf("Environment file not nil: %v", ef) - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/github.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/github.go deleted file mode 100644 index 2f7755fe..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/github.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "fmt" - - "github.com/coreos/coreos-cloudinit/system" -) - -func SSHImportGithubUser(system_user string, github_user string) error { - url := fmt.Sprintf("https://api.github.com/users/%s/keys", github_user) - keys, err := fetchUserKeys(url) - if err != nil { - return err - } - - key_name := fmt.Sprintf("github-%s", github_user) - return system.AuthorizeSSHKeys(system_user, key_name, keys) -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/ssh_keys.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/ssh_keys.go deleted file mode 100644 index 17b0c4a9..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/ssh_keys.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "encoding/json" - "fmt" - - "github.com/coreos/coreos-cloudinit/pkg" - "github.com/coreos/coreos-cloudinit/system" -) - -type UserKey struct { - ID int `json:"id,omitempty"` - Key string `json:"key"` -} - -func SSHImportKeysFromURL(system_user string, url string) error { - keys, err := fetchUserKeys(url) - if err != nil { - return err - } - - key_name := fmt.Sprintf("coreos-cloudinit-%s", system_user) - return system.AuthorizeSSHKeys(system_user, key_name, keys) -} - -func fetchUserKeys(url string) ([]string, error) { - client := pkg.NewHttpClient() - data, err := client.GetRetry(url) - if err != nil { - return nil, err - } - - var userKeys []UserKey - err = json.Unmarshal(data, &userKeys) - if err != nil { - return nil, err - } - keys := make([]string, 0) - for _, key := range userKeys { - keys = append(keys, key.Key) - } - return keys, err -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/ssh_keys_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/ssh_keys_test.go deleted file mode 100644 index 86395797..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/ssh_keys_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "fmt" - "net/http" - "net/http/httptest" - "testing" -) - -func TestCloudConfigUsersUrlMarshal(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - gh_res := ` -[ - { - "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAIHAu822ggSkIHrJYvhmBceOSVjuflfQm8RbMMDNVe9relQfuPbN+nxGGTCKzPLebeOcX+Wwi77TPXWwK3BZMglfXxhABlFPsuMb63Tqp94pBYsJdx/iFj9iGo6pKoM1k8ubOcqsUnq+BR9895zRbE7MjdwkGo67+QhCEwvkwAnNAAAAFQCuddVqXLCubzqnWmeHLQE+2GFfHwAAAIBnlXW5h15ndVuwi0htF4oodVSB1KwnTWcuBK+aE1zRs76yvRb0Ws+oifumThDwB/Tec6FQuAfRKfy6piChZqsu5KvL98I+2t5yyi1td+kMvdTnVL2lW44etDKseOcozmknCOmh4Dqvhl/2MwrDAhlPaN08EEq9h3w3mXtNLWH64QAAAIBAzDOKr17llngaKIdDXh+LtXKh87+zfjlTA36/9r2uF2kYE5uApDtu9sPCkt7+YBQt7R8prADPckwAiXwVdk0xijIOpLDBmoydQJJRQ+zTMxvpQmUr/1kUOv0zb+lB657CgvN0vVTmP2swPeMvgntt3C4vw7Ab+O+MS9peOAJbbQ==" - }, - { - "key": "ssh-dss AAAAB3NzaC1kc3MAAACBANxpzIbTzKTeBRaOIdUxwwGwvDasTfU/PonhbNIuhYjc+xFGvBRTumox2F+luVAKKs4WdvA4nJXaY1OFi6DZftk5Bp4E2JaSzp8ulAzHsMexDdv6LGHGEJj/qdHAL1vHk2K89PpwRFSRZI8XRBLjvkr4ZgBKLG5ZILXPJEPP2j3lAAAAFQCtxoTnV8wy0c4grcGrQ+1sCsD7WQAAAIAqZsW2GviMe1RQrbZT0xAZmI64XRPrnLsoLxycHWlS7r6uUln2c6Ae2MB/YF0d4Kd1XZii9GHj7rrypqEo7MW8uSabhu70nmu1J8m2O3Dsr+4oJLeat9vwPsJV92IKO0jQwjKnAOHOiB9JKGeCw+NfXfogbti9/q38Q6XcS+SI5wAAAIEA1803Y2h+tOOpZXAsNIwl9mRfExWzLQ3L7knwJdznQu/6SW1H/1oyoYLebuk187Qj2UFI5qQ6AZNc49DvohWx0Cg6ABcyubNyoaCjZKWIdxVnItHWNbLe//+tyTu0I2eQwJOORsEPK5gMpf599C7wXQ//DzZOWbTWiHEX52gCTmk=" - }, - { - "id": 5224438, - "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAPKRWdKhzGZuLAJL6M1eM51hWViMqNBC2C6lm2OqGRYLuIf1GJ391widUuSf4wQqnkR22Q9PCmAZ19XCf11wBRMnuw9I/Z3Bt5bXfc+dzFBCmHYGJ6wNSv++H9jxyMb+usmsenWOFZGNO2jN0wrJ4ay8Yt0bwtRU+VCXpuRLszMzAAAAFQDZUIuPjcfK5HLgnwZ/J3lvtvlUjQAAAIEApIkAwLuCQV5j3U6DmI/Y6oELqSUR2purFm8jo8jePFfe1t+ghikgD254/JXlhDCVgY0NLXcak+coJfGCTT23quJ7I5xdpTn/OZO2Q6Woum/bijFC/UWwQbLz0R2nU3DoHv5v6XHQZxuIG4Fsxa91S+vWjZFtI7RuYlBCZA//ANMAAACBAJO0FojzkX6IeaWLqrgu9GTkFwGFazZ+LPH5JOWPoPn1hQKuR32Uf6qNcBZcIjY7SF0P7HF5rLQd6zKZzHqqQQ92MV555NEwjsnJglYU8CaaZsfYooaGPgA1YN7RhTSAuDmUW5Hyfj5BH4NTtrzrvJxIhDoQLf31Fasjw00r4R0O" - } -] -` - fmt.Fprintln(w, gh_res) - })) - defer ts.Close() - - keys, err := fetchUserKeys(ts.URL) - if err != nil { - t.Fatalf("Encountered unexpected error: %v", err) - } - expected := "ssh-dss AAAAB3NzaC1kc3MAAACBAIHAu822ggSkIHrJYvhmBceOSVjuflfQm8RbMMDNVe9relQfuPbN+nxGGTCKzPLebeOcX+Wwi77TPXWwK3BZMglfXxhABlFPsuMb63Tqp94pBYsJdx/iFj9iGo6pKoM1k8ubOcqsUnq+BR9895zRbE7MjdwkGo67+QhCEwvkwAnNAAAAFQCuddVqXLCubzqnWmeHLQE+2GFfHwAAAIBnlXW5h15ndVuwi0htF4oodVSB1KwnTWcuBK+aE1zRs76yvRb0Ws+oifumThDwB/Tec6FQuAfRKfy6piChZqsu5KvL98I+2t5yyi1td+kMvdTnVL2lW44etDKseOcozmknCOmh4Dqvhl/2MwrDAhlPaN08EEq9h3w3mXtNLWH64QAAAIBAzDOKr17llngaKIdDXh+LtXKh87+zfjlTA36/9r2uF2kYE5uApDtu9sPCkt7+YBQt7R8prADPckwAiXwVdk0xijIOpLDBmoydQJJRQ+zTMxvpQmUr/1kUOv0zb+lB657CgvN0vVTmP2swPeMvgntt3C4vw7Ab+O+MS9peOAJbbQ==" - if keys[0] != expected { - t.Fatalf("expected %s, got %s", expected, keys[0]) - } - expected = "ssh-dss AAAAB3NzaC1kc3MAAACBAPKRWdKhzGZuLAJL6M1eM51hWViMqNBC2C6lm2OqGRYLuIf1GJ391widUuSf4wQqnkR22Q9PCmAZ19XCf11wBRMnuw9I/Z3Bt5bXfc+dzFBCmHYGJ6wNSv++H9jxyMb+usmsenWOFZGNO2jN0wrJ4ay8Yt0bwtRU+VCXpuRLszMzAAAAFQDZUIuPjcfK5HLgnwZ/J3lvtvlUjQAAAIEApIkAwLuCQV5j3U6DmI/Y6oELqSUR2purFm8jo8jePFfe1t+ghikgD254/JXlhDCVgY0NLXcak+coJfGCTT23quJ7I5xdpTn/OZO2Q6Woum/bijFC/UWwQbLz0R2nU3DoHv5v6XHQZxuIG4Fsxa91S+vWjZFtI7RuYlBCZA//ANMAAACBAJO0FojzkX6IeaWLqrgu9GTkFwGFazZ+LPH5JOWPoPn1hQKuR32Uf6qNcBZcIjY7SF0P7HF5rLQd6zKZzHqqQQ92MV555NEwjsnJglYU8CaaZsfYooaGPgA1YN7RhTSAuDmUW5Hyfj5BH4NTtrzrvJxIhDoQLf31Fasjw00r4R0O" - if keys[2] != expected { - t.Fatalf("expected %s, got %s", expected, keys[2]) - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/user_data.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/user_data.go deleted file mode 100644 index 170efaaa..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/user_data.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "errors" - "log" - - "github.com/coreos/coreos-cloudinit/config" -) - -func ParseUserData(contents string) (interface{}, error) { - if len(contents) == 0 { - return nil, nil - } - - switch { - case config.IsScript(contents): - log.Printf("Parsing user-data as script") - return config.NewScript(contents) - case config.IsCloudConfig(contents): - log.Printf("Parsing user-data as cloud-config") - return config.NewCloudConfig(contents) - default: - return nil, errors.New("Unrecognized user-data format") - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/user_data_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/user_data_test.go deleted file mode 100644 index 1d883694..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/user_data_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestParseHeaderCRLF(t *testing.T) { - configs := []string{ - "#cloud-config\nfoo: bar", - "#cloud-config\r\nfoo: bar", - } - - for i, config := range configs { - _, err := ParseUserData(config) - if err != nil { - t.Errorf("Failed parsing config %d: %v", i, err) - } - } - - scripts := []string{ - "#!bin/bash\necho foo", - "#!bin/bash\r\necho foo", - } - - for i, script := range scripts { - _, err := ParseUserData(script) - if err != nil { - t.Errorf("Failed parsing script %d: %v", i, err) - } - } -} - -func TestParseConfigCRLF(t *testing.T) { - contents := "#cloud-config\r\nhostname: foo\r\nssh_authorized_keys:\r\n - foobar\r\n" - ud, err := ParseUserData(contents) - if err != nil { - t.Fatalf("Failed parsing config: %v", err) - } - - cfg := ud.(*config.CloudConfig) - - if cfg.Hostname != "foo" { - t.Error("Failed parsing hostname from config") - } - - if len(cfg.SSHAuthorizedKeys) != 1 { - t.Error("Parsed incorrect number of SSH keys") - } -} - -func TestParseConfigEmpty(t *testing.T) { - i, e := ParseUserData(``) - if i != nil { - t.Error("ParseUserData of empty string returned non-nil unexpectedly") - } else if e != nil { - t.Error("ParseUserData of empty string returned error unexpectedly") - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/workspace.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/workspace.go deleted file mode 100644 index 540dcf41..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/initialize/workspace.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2015 CoreOS, Inc. -// -// 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 initialize - -import ( - "io/ioutil" - "path" - "strings" - - "github.com/coreos/coreos-cloudinit/config" - "github.com/coreos/coreos-cloudinit/system" -) - -func PrepWorkspace(workspace string) error { - if err := system.EnsureDirectoryExists(workspace); err != nil { - return err - } - - scripts := path.Join(workspace, "scripts") - if err := system.EnsureDirectoryExists(scripts); err != nil { - return err - } - - return nil -} - -func PersistScriptInWorkspace(script config.Script, workspace string) (string, error) { - scriptsPath := path.Join(workspace, "scripts") - tmp, err := ioutil.TempFile(scriptsPath, "") - if err != nil { - return "", err - } - tmp.Close() - - relpath := strings.TrimPrefix(tmp.Name(), workspace) - - file := system.File{File: config.File{ - Path: relpath, - RawFilePermissions: "0744", - Content: string(script), - }} - - return system.WriteFile(&file, workspace) -} - -func PersistUnitNameInWorkspace(name string, workspace string) error { - file := system.File{File: config.File{ - Path: path.Join("scripts", "unit-name"), - RawFilePermissions: "0644", - Content: name, - }} - _, err := system.WriteFile(&file, workspace) - return err -} diff --git a/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/project.go b/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/project.go index 686e6caa..61ae97aa 100644 --- a/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/project.go +++ b/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/project.go @@ -18,6 +18,12 @@ var ( ErrRestart error = errors.New("Restart execution") ) +type ProjectEvent struct { + Event Event + Service Service + Data map[string]string +} + func NewProject(name string, factory ServiceFactory) *Project { return &Project{ Name: name, @@ -72,6 +78,12 @@ func (p *Project) Up() error { } func (p *Project) startAll(wrappers map[string]*ServiceWrapper) error { + for name, _ := range p.Services { + if _, ok := wrappers[name]; !ok { + wrappers[name] = NewServiceWrapper(name, p) + } + } + restart := false for _, wrapper := range wrappers { @@ -176,6 +188,10 @@ func (s *ServiceWrapper) Wait() error { return s.err } +func (p *Project) AddListener(c chan<- ProjectEvent) { + p.listeners = append(p.listeners, c) +} + func (p *Project) Notify(event Event, service Service, data map[string]string) { buffer := bytes.NewBuffer(nil) if data != nil { @@ -204,4 +220,17 @@ func (p *Project) Notify(event Event, service Service, data map[string]string) { } else { logf("[%d/%d] [%s]: %s %s", p.upCount, len(p.Services), service.Name(), event, buffer.Bytes()) } + + for _, l := range p.listeners { + projectEvent := ProjectEvent{ + Event: event, + Service: service, + Data: data, + } + // Don't ever block + select { + case l <- projectEvent: + default: + } + } } diff --git a/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/types.go b/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/types.go index 938d1fcd..de9efa3e 100644 --- a/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/types.go +++ b/Godeps/_workspace/src/github.com/rancherio/rancher-compose/project/types.go @@ -66,6 +66,7 @@ type Project struct { factory ServiceFactory ReloadCallback func() error upCount int + listeners []chan<- ProjectEvent } type Service interface {