diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/config/config.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/config/config.go index 594597ec..5d34f7a8 100644 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/config/config.go +++ b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/config/config.go @@ -28,23 +28,12 @@ import ( // used for internal use) have the YAML tag '-' so that they aren't marshalled. type CloudConfig struct { SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys"` - CoreOS CoreOS `yaml:"coreos"` WriteFiles []File `yaml:"write_files"` Hostname string `yaml:"hostname"` Users []User `yaml:"users"` ManageEtcHosts EtcHosts `yaml:"manage_etc_hosts"` } -type CoreOS struct { - Etcd Etcd `yaml:"etcd"` - Flannel Flannel `yaml:"flannel"` - Fleet Fleet `yaml:"fleet"` - Locksmith Locksmith `yaml:"locksmith"` - OEM OEM `yaml:"oem"` - Update Update `yaml:"update"` - Units []Unit `yaml:"units"` -} - func IsCloudConfig(userdata string) bool { header := strings.SplitN(userdata, "\n", 2)[0] 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/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/system/etc_hosts.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etc_hosts.go deleted file mode 100644 index 7208c161..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etc_hosts.go +++ /dev/null @@ -1,62 +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 system - -import ( - "errors" - "fmt" - "os" - "path" - - "github.com/coreos/coreos-cloudinit/config" -) - -const DefaultIpv4Address = "127.0.0.1" - -type EtcHosts struct { - config.EtcHosts -} - -func (eh EtcHosts) generateEtcHosts() (out string, err error) { - if eh.EtcHosts != "localhost" { - return "", errors.New("Invalid option to manage_etc_hosts") - } - - // use the operating system hostname - hostname, err := os.Hostname() - if err != nil { - return "", err - } - - return fmt.Sprintf("%s %s\n", DefaultIpv4Address, hostname), nil - -} - -func (eh EtcHosts) File() (*File, error) { - if eh.EtcHosts == "" { - return nil, nil - } - - etcHosts, err := eh.generateEtcHosts() - if err != nil { - return nil, err - } - - return &File{config.File{ - Path: path.Join("etc", "hosts"), - RawFilePermissions: "0644", - Content: etcHosts, - }}, nil -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etc_hosts_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etc_hosts_test.go deleted file mode 100644 index e5efd7c4..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etc_hosts_test.go +++ /dev/null @@ -1,60 +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 system - -import ( - "fmt" - "os" - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestEtcdHostsFile(t *testing.T) { - hostname, err := os.Hostname() - if err != nil { - panic(err) - } - - for _, tt := range []struct { - config config.EtcHosts - file *File - err error - }{ - { - "invalid", - nil, - fmt.Errorf("Invalid option to manage_etc_hosts"), - }, - { - "localhost", - &File{config.File{ - Content: fmt.Sprintf("127.0.0.1 %s\n", hostname), - Path: "etc/hosts", - RawFilePermissions: "0644", - }}, - nil, - }, - } { - file, err := EtcHosts{tt.config}.File() - if !reflect.DeepEqual(tt.err, err) { - t.Errorf("bad error (%q): want %q, got %q", tt.config, tt.err, err) - } - if !reflect.DeepEqual(tt.file, file) { - t.Errorf("bad units (%q): want %#v, got %#v", tt.config, tt.file, file) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etcd.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etcd.go deleted file mode 100644 index 0c7faf4a..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etcd.go +++ /dev/null @@ -1,37 +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 system - -import ( - "github.com/coreos/coreos-cloudinit/config" -) - -// Etcd is a top-level structure which embeds its underlying configuration, -// config.Etcd, and provides the system-specific Unit(). -type Etcd struct { - config.Etcd -} - -// Units creates a Unit file drop-in for etcd, using any configured options. -func (ee Etcd) Units() []Unit { - return []Unit{{config.Unit{ - Name: "etcd.service", - Runtime: true, - DropIns: []config.UnitDropIn{{ - Name: "20-cloudinit.conf", - Content: serviceContents(ee.Etcd), - }}, - }}} -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etcd_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etcd_test.go deleted file mode 100644 index 5fc17f02..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/etcd_test.go +++ /dev/null @@ -1,79 +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 system - -import ( - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestEtcdUnits(t *testing.T) { - for _, tt := range []struct { - config config.Etcd - units []Unit - }{ - { - config.Etcd{}, - []Unit{{config.Unit{ - Name: "etcd.service", - Runtime: true, - DropIns: []config.UnitDropIn{{Name: "20-cloudinit.conf"}}, - }}}, - }, - { - config.Etcd{ - Discovery: "http://disco.example.com/foobar", - PeerBindAddr: "127.0.0.1:7002", - }, - []Unit{{config.Unit{ - Name: "etcd.service", - Runtime: true, - DropIns: []config.UnitDropIn{{ - Name: "20-cloudinit.conf", - Content: `[Service] -Environment="ETCD_DISCOVERY=http://disco.example.com/foobar" -Environment="ETCD_PEER_BIND_ADDR=127.0.0.1:7002" -`, - }}, - }}}, - }, - { - config.Etcd{ - Name: "node001", - Discovery: "http://disco.example.com/foobar", - PeerBindAddr: "127.0.0.1:7002", - }, - []Unit{{config.Unit{ - Name: "etcd.service", - Runtime: true, - DropIns: []config.UnitDropIn{{ - Name: "20-cloudinit.conf", - Content: `[Service] -Environment="ETCD_DISCOVERY=http://disco.example.com/foobar" -Environment="ETCD_NAME=node001" -Environment="ETCD_PEER_BIND_ADDR=127.0.0.1:7002" -`, - }}, - }}}, - }, - } { - units := Etcd{tt.config}.Units() - if !reflect.DeepEqual(tt.units, units) { - t.Errorf("bad units (%+v): want %#v, got %#v", tt.config, tt.units, units) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/flannel.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/flannel.go deleted file mode 100644 index 7442414c..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/flannel.go +++ /dev/null @@ -1,44 +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 system - -import ( - "path" - "strings" - - "github.com/coreos/coreos-cloudinit/config" -) - -// flannel is a top-level structure which embeds its underlying configuration, -// config.Flannel, and provides the system-specific Unit(). -type Flannel struct { - config.Flannel -} - -func (fl Flannel) envVars() string { - return strings.Join(getEnvVars(fl.Flannel), "\n") -} - -func (fl Flannel) File() (*File, error) { - vars := fl.envVars() - if vars == "" { - return nil, nil - } - return &File{config.File{ - Path: path.Join("run", "flannel", "options.env"), - RawFilePermissions: "0644", - Content: vars, - }}, nil -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/flannel_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/flannel_test.go deleted file mode 100644 index 7bc9f7f6..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/flannel_test.go +++ /dev/null @@ -1,76 +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 system - -import ( - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestFlannelEnvVars(t *testing.T) { - for _, tt := range []struct { - config config.Flannel - contents string - }{ - { - config.Flannel{}, - "", - }, - { - config.Flannel{ - EtcdEndpoints: "http://12.34.56.78:4001", - EtcdPrefix: "/coreos.com/network/tenant1", - }, - `FLANNELD_ETCD_ENDPOINTS=http://12.34.56.78:4001 -FLANNELD_ETCD_PREFIX=/coreos.com/network/tenant1`, - }, - } { - out := Flannel{tt.config}.envVars() - if out != tt.contents { - t.Errorf("bad contents (%+v): want %q, got %q", tt, tt.contents, out) - } - } -} - -func TestFlannelFile(t *testing.T) { - for _, tt := range []struct { - config config.Flannel - file *File - }{ - { - config.Flannel{}, - nil, - }, - { - config.Flannel{ - EtcdEndpoints: "http://12.34.56.78:4001", - EtcdPrefix: "/coreos.com/network/tenant1", - }, - &File{config.File{ - Path: "run/flannel/options.env", - RawFilePermissions: "0644", - Content: `FLANNELD_ETCD_ENDPOINTS=http://12.34.56.78:4001 -FLANNELD_ETCD_PREFIX=/coreos.com/network/tenant1`, - }}, - }, - } { - file, _ := Flannel{tt.config}.File() - if !reflect.DeepEqual(tt.file, file) { - t.Errorf("bad units (%q): want %#v, got %#v", tt.config, tt.file, file) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/fleet.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/fleet.go deleted file mode 100644 index 2d12d819..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/fleet.go +++ /dev/null @@ -1,38 +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 system - -import ( - "github.com/coreos/coreos-cloudinit/config" -) - -// Fleet is a top-level structure which embeds its underlying configuration, -// config.Fleet, and provides the system-specific Unit(). -type Fleet struct { - config.Fleet -} - -// Units generates a Unit file drop-in for fleet, if any fleet options were -// configured in cloud-config -func (fe Fleet) Units() []Unit { - return []Unit{{config.Unit{ - Name: "fleet.service", - Runtime: true, - DropIns: []config.UnitDropIn{{ - Name: "20-cloudinit.conf", - Content: serviceContents(fe.Fleet), - }}, - }}} -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/fleet_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/fleet_test.go deleted file mode 100644 index dfe7c3f5..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/fleet_test.go +++ /dev/null @@ -1,58 +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 system - -import ( - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestFleetUnits(t *testing.T) { - for _, tt := range []struct { - config config.Fleet - units []Unit - }{ - { - config.Fleet{}, - []Unit{{config.Unit{ - Name: "fleet.service", - Runtime: true, - DropIns: []config.UnitDropIn{{Name: "20-cloudinit.conf"}}, - }}}, - }, - { - config.Fleet{ - PublicIP: "12.34.56.78", - }, - []Unit{{config.Unit{ - Name: "fleet.service", - Runtime: true, - DropIns: []config.UnitDropIn{{ - Name: "20-cloudinit.conf", - Content: `[Service] -Environment="FLEET_PUBLIC_IP=12.34.56.78" -`, - }}, - }}}, - }, - } { - units := Fleet{tt.config}.Units() - if !reflect.DeepEqual(units, tt.units) { - t.Errorf("bad units (%+v): want %#v, got %#v", tt.config, tt.units, units) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/locksmith.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/locksmith.go deleted file mode 100644 index 6095e5f7..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/locksmith.go +++ /dev/null @@ -1,37 +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 system - -import ( - "github.com/coreos/coreos-cloudinit/config" -) - -// Locksmith is a top-level structure which embeds its underlying configuration, -// config.Locksmith, and provides the system-specific Unit(). -type Locksmith struct { - config.Locksmith -} - -// Units creates a Unit file drop-in for etcd, using any configured options. -func (ee Locksmith) Units() []Unit { - return []Unit{{config.Unit{ - Name: "locksmithd.service", - Runtime: true, - DropIns: []config.UnitDropIn{{ - Name: "20-cloudinit.conf", - Content: serviceContents(ee.Locksmith), - }}, - }}} -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/locksmith_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/locksmith_test.go deleted file mode 100644 index 6d7d9887..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/locksmith_test.go +++ /dev/null @@ -1,58 +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 system - -import ( - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestLocksmithUnits(t *testing.T) { - for _, tt := range []struct { - config config.Locksmith - units []Unit - }{ - { - config.Locksmith{}, - []Unit{{config.Unit{ - Name: "locksmithd.service", - Runtime: true, - DropIns: []config.UnitDropIn{{Name: "20-cloudinit.conf"}}, - }}}, - }, - { - config.Locksmith{ - Endpoint: "12.34.56.78:4001", - }, - []Unit{{config.Unit{ - Name: "locksmithd.service", - Runtime: true, - DropIns: []config.UnitDropIn{{ - Name: "20-cloudinit.conf", - Content: `[Service] -Environment="LOCKSMITHD_ENDPOINT=12.34.56.78:4001" -`, - }}, - }}}, - }, - } { - units := Locksmith{tt.config}.Units() - if !reflect.DeepEqual(units, tt.units) { - t.Errorf("bad units (%+v): want %#v, got %#v", tt.config, tt.units, units) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/networkd.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/networkd.go deleted file mode 100644 index 1e075ea0..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/networkd.go +++ /dev/null @@ -1,96 +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 system - -import ( - "fmt" - "log" - "net" - "os/exec" - "strings" - - "github.com/coreos/coreos-cloudinit/config" - "github.com/coreos/coreos-cloudinit/network" - - "github.com/docker/libcontainer/netlink" -) - -func RestartNetwork(interfaces []network.InterfaceGenerator) (err error) { - defer func() { - if e := restartNetworkd(); e != nil { - err = e - } - }() - - if err = downNetworkInterfaces(interfaces); err != nil { - return - } - - if err = maybeProbe8012q(interfaces); err != nil { - return - } - return maybeProbeBonding(interfaces) -} - -func downNetworkInterfaces(interfaces []network.InterfaceGenerator) error { - sysInterfaceMap := make(map[string]*net.Interface) - if systemInterfaces, err := net.Interfaces(); err == nil { - for _, iface := range systemInterfaces { - iface := iface - sysInterfaceMap[iface.Name] = &iface - } - } else { - return err - } - - for _, iface := range interfaces { - if systemInterface, ok := sysInterfaceMap[iface.Name()]; ok { - log.Printf("Taking down interface %q\n", systemInterface.Name) - if err := netlink.NetworkLinkDown(systemInterface); err != nil { - fmt.Printf("Error while downing interface %q (%s). Continuing...\n", systemInterface.Name, err) - } - } - } - - return nil -} - -func maybeProbe8012q(interfaces []network.InterfaceGenerator) error { - for _, iface := range interfaces { - if iface.Type() == "vlan" { - log.Printf("Probing LKM %q (%q)\n", "8021q", "8021q") - return exec.Command("modprobe", "8021q").Run() - } - } - return nil -} - -func maybeProbeBonding(interfaces []network.InterfaceGenerator) error { - for _, iface := range interfaces { - if iface.Type() == "bond" { - args := append([]string{"bonding"}, strings.Split(iface.ModprobeParams(), " ")...) - log.Printf("Probing LKM %q (%q)\n", "bonding", args) - return exec.Command("modprobe", args...).Run() - } - } - return nil -} - -func restartNetworkd() error { - log.Printf("Restarting networkd.service\n") - networkd := Unit{config.Unit{Name: "systemd-networkd.service"}} - _, err := NewUnitManager("").RunUnitCommand(networkd, "restart") - return err -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/oem.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/oem.go deleted file mode 100644 index b77e9c8b..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/oem.go +++ /dev/null @@ -1,46 +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 system - -import ( - "fmt" - "path" - - "github.com/coreos/coreos-cloudinit/config" -) - -// OEM is a top-level structure which embeds its underlying configuration, -// config.OEM, and provides the system-specific File(). -type OEM struct { - config.OEM -} - -func (oem OEM) File() (*File, error) { - if oem.ID == "" { - return nil, nil - } - - content := fmt.Sprintf("ID=%s\n", oem.ID) - content += fmt.Sprintf("VERSION_ID=%s\n", oem.VersionID) - content += fmt.Sprintf("NAME=%q\n", oem.Name) - content += fmt.Sprintf("HOME_URL=%q\n", oem.HomeURL) - content += fmt.Sprintf("BUG_REPORT_URL=%q\n", oem.BugReportURL) - - return &File{config.File{ - Path: path.Join("etc", "oem-release"), - RawFilePermissions: "0644", - Content: content, - }}, nil -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/oem_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/oem_test.go deleted file mode 100644 index 38661201..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/oem_test.go +++ /dev/null @@ -1,61 +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 system - -import ( - "reflect" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestOEMFile(t *testing.T) { - for _, tt := range []struct { - config config.OEM - file *File - }{ - { - config.OEM{}, - nil, - }, - { - config.OEM{ - ID: "rackspace", - Name: "Rackspace Cloud Servers", - VersionID: "168.0.0", - HomeURL: "https://www.rackspace.com/cloud/servers/", - BugReportURL: "https://github.com/coreos/coreos-overlay", - }, - &File{config.File{ - Path: "etc/oem-release", - RawFilePermissions: "0644", - Content: `ID=rackspace -VERSION_ID=168.0.0 -NAME="Rackspace Cloud Servers" -HOME_URL="https://www.rackspace.com/cloud/servers/" -BUG_REPORT_URL="https://github.com/coreos/coreos-overlay" -`, - }}, - }, - } { - file, err := OEM{tt.config}.File() - if err != nil { - t.Errorf("bad error (%q): want %v, got %q", tt.config, nil, err) - } - if !reflect.DeepEqual(tt.file, file) { - t.Errorf("bad file (%q): want %#v, got %#v", tt.config, tt.file, file) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/ssh_key.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/ssh_key.go index 9811422a..fd2593c2 100644 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/ssh_key.go +++ b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/ssh_key.go @@ -16,8 +16,6 @@ package system import ( "fmt" - "io" - "io/ioutil" "os/exec" "strings" ) @@ -25,48 +23,19 @@ import ( // Add the provide SSH public key to the core user's list of // authorized keys func AuthorizeSSHKeys(user string, keysName string, keys []string) error { - for i, key := range keys { - keys[i] = strings.TrimSpace(key) - } + for _, key := range keys { + trimmedKey := strings.TrimSpace(key) + cmd := exec.Command("update-ssh-keys", user, trimmedKey) - // join all keys with newlines, ensuring the resulting string - // also ends with a newline - joined := fmt.Sprintf("%s\n", strings.Join(keys, "\n")) + err := cmd.Start() + if err != nil { + return err + } - cmd := exec.Command("update-ssh-keys", "-u", user, "-a", keysName) - stdin, err := cmd.StdinPipe() - if err != nil { - return err - } - - stdout, err := cmd.StdoutPipe() - if err != nil { - return err - } - - stderr, err := cmd.StderrPipe() - if err != nil { - return err - } - - err = cmd.Start() - if err != nil { - stdin.Close() - return err - } - - _, err = io.WriteString(stdin, joined) - if err != nil { - return err - } - - stdin.Close() - stdoutBytes, _ := ioutil.ReadAll(stdout) - stderrBytes, _ := ioutil.ReadAll(stderr) - - err = cmd.Wait() - if err != nil { - return fmt.Errorf("Call to update-ssh-keys failed with %v: %s %s", err, string(stdoutBytes), string(stderrBytes)) + err = cmd.Wait() + if err != nil { + return fmt.Errorf("Call to update-ssh-keys failed") + } } return nil diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/systemd.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/systemd.go deleted file mode 100644 index 190b9e77..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/systemd.go +++ /dev/null @@ -1,205 +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 system - -import ( - "fmt" - "io/ioutil" - "log" - "os" - "os/exec" - "path" - "strings" - - "github.com/coreos/go-systemd/dbus" - "github.com/coreos/coreos-cloudinit/config" -) - -func NewUnitManager(root string) UnitManager { - return &systemd{root} -} - -type systemd struct { - root string -} - -// fakeMachineID is placed on non-usr CoreOS images and should -// never be used as a true MachineID -const fakeMachineID = "42000000000000000000000000000042" - -// PlaceUnit writes a unit file at its desired destination, creating parent -// directories as necessary. -func (s *systemd) PlaceUnit(u Unit) error { - file := File{config.File{ - Path: u.Destination(s.root), - Content: u.Content, - RawFilePermissions: "0644", - }} - - _, err := WriteFile(&file, "/") - return err -} - -// PlaceUnitDropIn writes a unit drop-in file at its desired destination, -// creating parent directories as necessary. -func (s *systemd) PlaceUnitDropIn(u Unit, d config.UnitDropIn) error { - file := File{config.File{ - Path: u.DropInDestination(s.root, d), - Content: d.Content, - RawFilePermissions: "0644", - }} - - _, err := WriteFile(&file, "/") - return err -} - -func (s *systemd) EnableUnitFile(u Unit) error { - conn, err := dbus.New() - if err != nil { - return err - } - - units := []string{u.Name} - _, _, err = conn.EnableUnitFiles(units, u.Runtime, true) - return err -} - -func (s *systemd) RunUnitCommand(u Unit, c string) (string, error) { - conn, err := dbus.New() - if err != nil { - return "", err - } - - var fn func(string, string) (string, error) - switch c { - case "start": - fn = conn.StartUnit - case "stop": - fn = conn.StopUnit - case "restart": - fn = conn.RestartUnit - case "reload": - fn = conn.ReloadUnit - case "try-restart": - fn = conn.TryRestartUnit - case "reload-or-restart": - fn = conn.ReloadOrRestartUnit - case "reload-or-try-restart": - fn = conn.ReloadOrTryRestartUnit - default: - return "", fmt.Errorf("Unsupported systemd command %q", c) - } - - return fn(u.Name, "replace") -} - -func (s *systemd) DaemonReload() error { - conn, err := dbus.New() - if err != nil { - return err - } - - return conn.Reload() -} - -// MaskUnit masks the given Unit by symlinking its unit file to -// /dev/null, analogous to `systemctl mask`. -// N.B.: Unlike `systemctl mask`, this function will *remove any existing unit -// file at the location*, to ensure that the mask will succeed. -func (s *systemd) MaskUnit(u Unit) error { - masked := u.Destination(s.root) - if _, err := os.Stat(masked); os.IsNotExist(err) { - if err := os.MkdirAll(path.Dir(masked), os.FileMode(0755)); err != nil { - return err - } - } else if err := os.Remove(masked); err != nil { - return err - } - return os.Symlink("/dev/null", masked) -} - -// UnmaskUnit is analogous to systemd's unit_file_unmask. If the file -// associated with the given Unit is empty or appears to be a symlink to -// /dev/null, it is removed. -func (s *systemd) UnmaskUnit(u Unit) error { - masked := u.Destination(s.root) - ne, err := nullOrEmpty(masked) - if os.IsNotExist(err) { - return nil - } else if err != nil { - return err - } - if !ne { - log.Printf("%s is not null or empty, refusing to unmask", masked) - return nil - } - return os.Remove(masked) -} - -// nullOrEmpty checks whether a given path appears to be an empty regular file -// or a symlink to /dev/null -func nullOrEmpty(path string) (bool, error) { - fi, err := os.Stat(path) - if err != nil { - return false, err - } - m := fi.Mode() - if m.IsRegular() && fi.Size() <= 0 { - return true, nil - } - if m&os.ModeCharDevice > 0 { - return true, nil - } - return false, nil -} - -func ExecuteScript(scriptPath string) (string, error) { - props := []dbus.Property{ - dbus.PropDescription("Unit generated and executed by coreos-cloudinit on behalf of user"), - dbus.PropExecStart([]string{"/bin/bash", scriptPath}, false), - } - - base := path.Base(scriptPath) - name := fmt.Sprintf("coreos-cloudinit-%s.service", base) - - log.Printf("Creating transient systemd unit '%s'", name) - - conn, err := dbus.New() - if err != nil { - return "", err - } - - _, err = conn.StartTransientUnit(name, "replace", props...) - return name, err -} - -func SetHostname(hostname string) error { - return exec.Command("hostnamectl", "set-hostname", hostname).Run() -} - -func Hostname() (string, error) { - return os.Hostname() -} - -func MachineID(root string) string { - contents, _ := ioutil.ReadFile(path.Join(root, "etc", "machine-id")) - id := strings.TrimSpace(string(contents)) - - if id == fakeMachineID { - id = "" - } - - return id -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/systemd_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/systemd_test.go deleted file mode 100644 index 82052abc..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/systemd_test.go +++ /dev/null @@ -1,280 +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 system - -import ( - "fmt" - "io/ioutil" - "os" - "path" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestPlaceUnit(t *testing.T) { - tests := []config.Unit{ - { - Name: "50-eth0.network", - Runtime: true, - Content: "[Match]\nName=eth47\n\n[Network]\nAddress=10.209.171.177/19\n", - }, - { - Name: "media-state.mount", - Content: "[Mount]\nWhat=/dev/sdb1\nWhere=/media/state\n", - }, - } - - for _, tt := range tests { - dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-") - if err != nil { - panic(fmt.Sprintf("Unable to create tempdir: %v", err)) - } - - u := Unit{tt} - sd := &systemd{dir} - - if err := sd.PlaceUnit(u); err != nil { - t.Fatalf("PlaceUnit(): bad error (%+v): want nil, got %s", tt, err) - } - - fi, err := os.Stat(u.Destination(dir)) - if err != nil { - t.Fatalf("Stat(): bad error (%+v): want nil, got %s", tt, err) - } - - if mode := fi.Mode(); mode != os.FileMode(0644) { - t.Errorf("bad filemode (%+v): want %v, got %v", tt, os.FileMode(0644), mode) - } - - c, err := ioutil.ReadFile(u.Destination(dir)) - if err != nil { - t.Fatalf("ReadFile(): bad error (%+v): want nil, got %s", tt, err) - } - - if string(c) != tt.Content { - t.Errorf("bad contents (%+v): want %q, got %q", tt, tt.Content, string(c)) - } - - os.RemoveAll(dir) - } -} - -func TestPlaceUnitDropIn(t *testing.T) { - tests := []config.Unit{ - { - Name: "false.service", - Runtime: true, - DropIns: []config.UnitDropIn{ - { - Name: "00-true.conf", - Content: "[Service]\nExecStart=\nExecStart=/usr/bin/true\n", - }, - }, - }, - { - Name: "true.service", - DropIns: []config.UnitDropIn{ - { - Name: "00-false.conf", - Content: "[Service]\nExecStart=\nExecStart=/usr/bin/false\n", - }, - }, - }, - } - - for _, tt := range tests { - dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-") - if err != nil { - panic(fmt.Sprintf("Unable to create tempdir: %v", err)) - } - - u := Unit{tt} - sd := &systemd{dir} - - if err := sd.PlaceUnitDropIn(u, u.DropIns[0]); err != nil { - t.Fatalf("PlaceUnit(): bad error (%+v): want nil, got %s", tt, err) - } - - fi, err := os.Stat(u.DropInDestination(dir, u.DropIns[0])) - if err != nil { - t.Fatalf("Stat(): bad error (%+v): want nil, got %s", tt, err) - } - - if mode := fi.Mode(); mode != os.FileMode(0644) { - t.Errorf("bad filemode (%+v): want %v, got %v", tt, os.FileMode(0644), mode) - } - - c, err := ioutil.ReadFile(u.DropInDestination(dir, u.DropIns[0])) - if err != nil { - t.Fatalf("ReadFile(): bad error (%+v): want nil, got %s", tt, err) - } - - if string(c) != u.DropIns[0].Content { - t.Errorf("bad contents (%+v): want %q, got %q", tt, u.DropIns[0].Content, string(c)) - } - - os.RemoveAll(dir) - } -} - -func TestMachineID(t *testing.T) { - dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-") - if err != nil { - t.Fatalf("Unable to create tempdir: %v", err) - } - defer os.RemoveAll(dir) - - os.Mkdir(path.Join(dir, "etc"), os.FileMode(0755)) - ioutil.WriteFile(path.Join(dir, "etc", "machine-id"), []byte("node007\n"), os.FileMode(0444)) - - if MachineID(dir) != "node007" { - t.Fatalf("File has incorrect contents") - } -} - -func TestMaskUnit(t *testing.T) { - dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-") - if err != nil { - t.Fatalf("Unable to create tempdir: %v", err) - } - defer os.RemoveAll(dir) - - sd := &systemd{dir} - - // Ensure mask works with units that do not currently exist - uf := Unit{config.Unit{Name: "foo.service"}} - if err := sd.MaskUnit(uf); err != nil { - t.Fatalf("Unable to mask new unit: %v", err) - } - fooPath := path.Join(dir, "etc", "systemd", "system", "foo.service") - fooTgt, err := os.Readlink(fooPath) - if err != nil { - t.Fatal("Unable to read link", err) - } - if fooTgt != "/dev/null" { - t.Fatal("unit not masked, got unit target", fooTgt) - } - - // Ensure mask works with unit files that already exist - ub := Unit{config.Unit{Name: "bar.service"}} - barPath := path.Join(dir, "etc", "systemd", "system", "bar.service") - if _, err := os.Create(barPath); err != nil { - t.Fatalf("Error creating new unit file: %v", err) - } - if err := sd.MaskUnit(ub); err != nil { - t.Fatalf("Unable to mask existing unit: %v", err) - } - barTgt, err := os.Readlink(barPath) - if err != nil { - t.Fatal("Unable to read link", err) - } - if barTgt != "/dev/null" { - t.Fatal("unit not masked, got unit target", barTgt) - } -} - -func TestUnmaskUnit(t *testing.T) { - dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-") - if err != nil { - t.Fatalf("Unable to create tempdir: %v", err) - } - defer os.RemoveAll(dir) - - sd := &systemd{dir} - - nilUnit := Unit{config.Unit{Name: "null.service"}} - if err := sd.UnmaskUnit(nilUnit); err != nil { - t.Errorf("unexpected error from unmasking nonexistent unit: %v", err) - } - - uf := Unit{config.Unit{Name: "foo.service", Content: "[Service]\nExecStart=/bin/true"}} - dst := uf.Destination(dir) - if err := os.MkdirAll(path.Dir(dst), os.FileMode(0755)); err != nil { - t.Fatalf("Unable to create unit directory: %v", err) - } - if _, err := os.Create(dst); err != nil { - t.Fatalf("Unable to write unit file: %v", err) - } - - if err := ioutil.WriteFile(dst, []byte(uf.Content), 700); err != nil { - t.Fatalf("Unable to write unit file: %v", err) - } - if err := sd.UnmaskUnit(uf); err != nil { - t.Errorf("unmask of non-empty unit returned unexpected error: %v", err) - } - got, _ := ioutil.ReadFile(dst) - if string(got) != uf.Content { - t.Errorf("unmask of non-empty unit mutated unit contents unexpectedly") - } - - ub := Unit{config.Unit{Name: "bar.service"}} - dst = ub.Destination(dir) - if err := os.Symlink("/dev/null", dst); err != nil { - t.Fatalf("Unable to create masked unit: %v", err) - } - if err := sd.UnmaskUnit(ub); err != nil { - t.Errorf("unmask of unit returned unexpected error: %v", err) - } - if _, err := os.Stat(dst); !os.IsNotExist(err) { - t.Errorf("expected %s to not exist after unmask, but got err: %s", dst, err) - } -} - -func TestNullOrEmpty(t *testing.T) { - dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-") - if err != nil { - t.Fatalf("Unable to create tempdir: %v", err) - } - defer os.RemoveAll(dir) - - non := path.Join(dir, "does_not_exist") - ne, err := nullOrEmpty(non) - if !os.IsNotExist(err) { - t.Errorf("nullOrEmpty on nonexistent file returned bad error: %v", err) - } - if ne { - t.Errorf("nullOrEmpty returned true unxpectedly") - } - - regEmpty := path.Join(dir, "regular_empty_file") - _, err = os.Create(regEmpty) - if err != nil { - t.Fatalf("Unable to create tempfile: %v", err) - } - gotNe, gotErr := nullOrEmpty(regEmpty) - if !gotNe || gotErr != nil { - t.Errorf("nullOrEmpty of regular empty file returned %t, %v - want true, nil", gotNe, gotErr) - } - - reg := path.Join(dir, "regular_file") - if err := ioutil.WriteFile(reg, []byte("asdf"), 700); err != nil { - t.Fatalf("Unable to create tempfile: %v", err) - } - gotNe, gotErr = nullOrEmpty(reg) - if gotNe || gotErr != nil { - t.Errorf("nullOrEmpty of regular file returned %t, %v - want false, nil", gotNe, gotErr) - } - - null := path.Join(dir, "null") - if err := os.Symlink(os.DevNull, null); err != nil { - t.Fatalf("Unable to create /dev/null link: %s", err) - } - gotNe, gotErr = nullOrEmpty(null) - if !gotNe || gotErr != nil { - t.Errorf("nullOrEmpty of null symlink returned %t, %v - want true, nil", gotNe, gotErr) - } - -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/unit.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/unit.go deleted file mode 100644 index 22d006d1..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/unit.go +++ /dev/null @@ -1,82 +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 system - -import ( - "fmt" - "path" - "path/filepath" - "strings" - - "github.com/coreos/coreos-cloudinit/config" -) - -type UnitManager interface { - PlaceUnit(unit Unit) error - PlaceUnitDropIn(unit Unit, dropIn config.UnitDropIn) error - EnableUnitFile(unit Unit) error - RunUnitCommand(unit Unit, command string) (string, error) - MaskUnit(unit Unit) error - UnmaskUnit(unit Unit) error - DaemonReload() error -} - -// Unit is a top-level structure which embeds its underlying configuration, -// config.Unit, and provides the system-specific Destination(), Type(), and -// Group(). -type Unit struct { - config.Unit -} - -// Type returns the extension of the unit (everything that follows the final -// period). -func (u Unit) Type() string { - ext := filepath.Ext(u.Name) - return strings.TrimLeft(ext, ".") -} - -// Group returns "network" or "system" depending on whether or not the unit is -// a network unit or otherwise. -func (u Unit) Group() string { - switch u.Type() { - case "network", "netdev", "link": - return "network" - default: - return "system" - } -} - -// Destination builds the appropriate absolute file path for the Unit. The root -// argument indicates the effective base directory of the system (similar to a -// chroot). -func (u Unit) Destination(root string) string { - return path.Join(u.prefix(root), u.Name) -} - -// DropInDestination builds the appropriate absolute file path for the -// UnitDropIn. The root argument indicates the effective base directory of the -// system (similar to a chroot) and the dropIn argument is the UnitDropIn for -// which the destination is being calculated. -func (u Unit) DropInDestination(root string, dropIn config.UnitDropIn) string { - return path.Join(u.prefix(root), fmt.Sprintf("%s.d", u.Name), dropIn.Name) -} - -func (u Unit) prefix(root string) string { - dir := "etc" - if u.Runtime { - dir = "run" - } - return path.Join(root, dir, "systemd", u.Group()) -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/unit_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/unit_test.go deleted file mode 100644 index c995b592..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/unit_test.go +++ /dev/null @@ -1,136 +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 system - -import ( - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func TestType(t *testing.T) { - tests := []struct { - name string - - typ string - }{ - {}, - {"test.service", "service"}, - {"hello", ""}, - {"lots.of.dots", "dots"}, - } - - for _, tt := range tests { - u := Unit{config.Unit{ - Name: tt.name, - }} - if typ := u.Type(); tt.typ != typ { - t.Errorf("bad type (%+v): want %q, got %q", tt, tt.typ, typ) - } - } -} - -func TestGroup(t *testing.T) { - tests := []struct { - name string - - group string - }{ - {"test.service", "system"}, - {"test.link", "network"}, - {"test.network", "network"}, - {"test.netdev", "network"}, - {"test.conf", "system"}, - } - - for _, tt := range tests { - u := Unit{config.Unit{ - Name: tt.name, - }} - if group := u.Group(); tt.group != group { - t.Errorf("bad group (%+v): want %q, got %q", tt, tt.group, group) - } - } -} - -func TestDestination(t *testing.T) { - tests := []struct { - root string - name string - runtime bool - - destination string - }{ - { - root: "/some/dir", - name: "foobar.service", - destination: "/some/dir/etc/systemd/system/foobar.service", - }, - { - root: "/some/dir", - name: "foobar.service", - runtime: true, - destination: "/some/dir/run/systemd/system/foobar.service", - }, - } - - for _, tt := range tests { - u := Unit{config.Unit{ - Name: tt.name, - Runtime: tt.runtime, - }} - if d := u.Destination(tt.root); tt.destination != d { - t.Errorf("bad destination (%+v): want %q, got %q", tt, tt.destination, d) - } - } -} - -func TestDropInDestination(t *testing.T) { - tests := []struct { - root string - unitName string - dropInName string - runtime bool - - destination string - }{ - { - root: "/some/dir", - unitName: "foo.service", - dropInName: "bar.conf", - destination: "/some/dir/etc/systemd/system/foo.service.d/bar.conf", - }, - { - root: "/some/dir", - unitName: "foo.service", - dropInName: "bar.conf", - runtime: true, - destination: "/some/dir/run/systemd/system/foo.service.d/bar.conf", - }, - } - - for _, tt := range tests { - u := Unit{config.Unit{ - Name: tt.unitName, - Runtime: tt.runtime, - DropIns: []config.UnitDropIn{{ - Name: tt.dropInName, - }}, - }} - if d := u.DropInDestination(tt.root, u.DropIns[0]); tt.destination != d { - t.Errorf("bad destination (%+v): want %q, got %q", tt, tt.destination, d) - } - } -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/update.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/update.go deleted file mode 100644 index 5e92dace..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/update.go +++ /dev/null @@ -1,151 +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 system - -import ( - "bufio" - "fmt" - "io" - "os" - "path" - "reflect" - "sort" - "strings" - - "github.com/coreos/coreos-cloudinit/config" -) - -const ( - locksmithUnit = "locksmithd.service" - updateEngineUnit = "update-engine.service" -) - -// Update is a top-level structure which contains its underlying configuration, -// config.Update, a function for reading the configuration (the default -// implementation reading from the filesystem), and provides the system-specific -// File() and Unit(). -type Update struct { - ReadConfig func() (io.Reader, error) - config.Update -} - -func DefaultReadConfig() (io.Reader, error) { - etcUpdate := path.Join("/etc", "coreos", "update.conf") - usrUpdate := path.Join("/usr", "share", "coreos", "update.conf") - - f, err := os.Open(etcUpdate) - if os.IsNotExist(err) { - f, err = os.Open(usrUpdate) - } - return f, err -} - -// File generates an `/etc/coreos/update.conf` file (if any update -// configuration options are set in cloud-config) by either rewriting the -// existing file on disk, or starting from `/usr/share/coreos/update.conf` -func (uc Update) File() (*File, error) { - if config.IsZero(uc.Update) { - return nil, nil - } - if err := config.AssertStructValid(uc.Update); err != nil { - return nil, err - } - - // Generate the list of possible substitutions to be performed based on the options that are configured - subs := map[string]string{} - uct := reflect.TypeOf(uc.Update) - ucv := reflect.ValueOf(uc.Update) - for i := 0; i < uct.NumField(); i++ { - val := ucv.Field(i).String() - if val == "" { - continue - } - env := uct.Field(i).Tag.Get("env") - subs[env] = fmt.Sprintf("%s=%s", env, val) - } - - conf, err := uc.ReadConfig() - if err != nil { - return nil, err - } - scanner := bufio.NewScanner(conf) - - var out string - for scanner.Scan() { - line := scanner.Text() - for env, value := range subs { - if strings.HasPrefix(line, env) { - line = value - delete(subs, env) - break - } - } - out += line - out += "\n" - if err := scanner.Err(); err != nil { - return nil, err - } - } - - for _, key := range sortedKeys(subs) { - out += subs[key] - out += "\n" - } - - return &File{config.File{ - Path: path.Join("etc", "coreos", "update.conf"), - RawFilePermissions: "0644", - Content: out, - }}, nil -} - -// Units generates units for the cloud-init initializer to act on: -// - a locksmith Unit, if "reboot-strategy" was set in cloud-config -// - an update_engine Unit, if "group" or "server" was set in cloud-config -func (uc Update) Units() []Unit { - var units []Unit - if uc.Update.RebootStrategy != "" { - ls := &Unit{config.Unit{ - Name: locksmithUnit, - Command: "restart", - Mask: false, - Runtime: true, - }} - - if uc.Update.RebootStrategy == "off" { - ls.Command = "stop" - ls.Mask = true - } - units = append(units, *ls) - } - - if uc.Update.Group != "" || uc.Update.Server != "" { - ue := Unit{config.Unit{ - Name: updateEngineUnit, - Command: "restart", - }} - units = append(units, ue) - } - - return units -} - -func sortedKeys(m map[string]string) (keys []string) { - for key := range m { - keys = append(keys, key) - } - sort.Strings(keys) - return -} diff --git a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/update_test.go b/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/update_test.go deleted file mode 100644 index ae3972b8..00000000 --- a/Godeps/_workspace/src/github.com/coreos/coreos-cloudinit/system/update_test.go +++ /dev/null @@ -1,161 +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 system - -import ( - "io" - "reflect" - "strings" - "testing" - - "github.com/coreos/coreos-cloudinit/config" -) - -func testReadConfig(config string) func() (io.Reader, error) { - return func() (io.Reader, error) { - return strings.NewReader(config), nil - } -} - -func TestUpdateUnits(t *testing.T) { - for _, tt := range []struct { - config config.Update - units []Unit - err error - }{ - { - config: config.Update{}, - }, - { - config: config.Update{Group: "master", Server: "http://foo.com"}, - units: []Unit{{config.Unit{ - Name: "update-engine.service", - Command: "restart", - }}}, - }, - { - config: config.Update{RebootStrategy: "best-effort"}, - units: []Unit{{config.Unit{ - Name: "locksmithd.service", - Command: "restart", - Runtime: true, - }}}, - }, - { - config: config.Update{RebootStrategy: "etcd-lock"}, - units: []Unit{{config.Unit{ - Name: "locksmithd.service", - Command: "restart", - Runtime: true, - }}}, - }, - { - config: config.Update{RebootStrategy: "reboot"}, - units: []Unit{{config.Unit{ - Name: "locksmithd.service", - Command: "restart", - Runtime: true, - }}}, - }, - { - config: config.Update{RebootStrategy: "off"}, - units: []Unit{{config.Unit{ - Name: "locksmithd.service", - Command: "stop", - Runtime: true, - Mask: true, - }}}, - }, - } { - units := Update{Update: tt.config, ReadConfig: testReadConfig("")}.Units() - if !reflect.DeepEqual(tt.units, units) { - t.Errorf("bad units (%q): want %#v, got %#v", tt.config, tt.units, units) - } - } -} - -func TestUpdateFile(t *testing.T) { - for _, tt := range []struct { - config config.Update - orig string - file *File - err error - }{ - { - config: config.Update{}, - }, - { - config: config.Update{RebootStrategy: "wizzlewazzle"}, - err: &config.ErrorValid{Value: "wizzlewazzle", Field: "RebootStrategy", Valid: "^(best-effort|etcd-lock|reboot|off)$"}, - }, - { - config: config.Update{Group: "master", Server: "http://foo.com"}, - file: &File{config.File{ - Content: "GROUP=master\nSERVER=http://foo.com\n", - Path: "etc/coreos/update.conf", - RawFilePermissions: "0644", - }}, - }, - { - config: config.Update{RebootStrategy: "best-effort"}, - file: &File{config.File{ - Content: "REBOOT_STRATEGY=best-effort\n", - Path: "etc/coreos/update.conf", - RawFilePermissions: "0644", - }}, - }, - { - config: config.Update{RebootStrategy: "etcd-lock"}, - file: &File{config.File{ - Content: "REBOOT_STRATEGY=etcd-lock\n", - Path: "etc/coreos/update.conf", - RawFilePermissions: "0644", - }}, - }, - { - config: config.Update{RebootStrategy: "reboot"}, - file: &File{config.File{ - Content: "REBOOT_STRATEGY=reboot\n", - Path: "etc/coreos/update.conf", - RawFilePermissions: "0644", - }}, - }, - { - config: config.Update{RebootStrategy: "off"}, - file: &File{config.File{ - Content: "REBOOT_STRATEGY=off\n", - Path: "etc/coreos/update.conf", - RawFilePermissions: "0644", - }}, - }, - { - config: config.Update{RebootStrategy: "etcd-lock"}, - orig: "SERVER=https://example.com\nGROUP=thegroupc\nREBOOT_STRATEGY=awesome", - file: &File{config.File{ - Content: "SERVER=https://example.com\nGROUP=thegroupc\nREBOOT_STRATEGY=etcd-lock\n", - Path: "etc/coreos/update.conf", - RawFilePermissions: "0644", - }}, - }, - } { - file, err := Update{Update: tt.config, ReadConfig: testReadConfig(tt.orig)}.File() - if !reflect.DeepEqual(tt.err, err) { - t.Errorf("bad error (%q): want %q, got %q", tt.config, tt.err, err) - } - if !reflect.DeepEqual(tt.file, file) { - t.Errorf("bad units (%q): want %#v, got %#v", tt.config, tt.file, file) - } - } -} diff --git a/cmd/cloudinit/authorizeSSHKeys.go b/cmd/cloudinit/authorizeSSHKeys.go new file mode 100644 index 00000000..606bba38 --- /dev/null +++ b/cmd/cloudinit/authorizeSSHKeys.go @@ -0,0 +1,17 @@ +package cloudinit + +import( + "os/exec" + + log "github.com/Sirupsen/logrus" +) + +func authorizeSSHKeys(user string, authorizedKeys []string, name string) { + for _, authorizedKey := range authorizedKeys { + cmd := exec.Command("update-ssh-keys", user, authorizedKey) + err := cmd.Run() + if err != nil { + log.Fatal(err.Error()) + } + } +} diff --git a/cmd/cloudinit/cloudinit.go b/cmd/cloudinit/cloudinit.go index 5b6d096b..14357693 100644 --- a/cmd/cloudinit/cloudinit.go +++ b/cmd/cloudinit/cloudinit.go @@ -1,18 +1,3 @@ -// Copyright 2015 CoreOS, Inc. -// Copyright 2015 Rancher Labs, 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 cloudinit import ( @@ -20,7 +5,9 @@ import ( "fmt" "io/ioutil" "os" + "os/exec" "path" + "reflect" "strings" "sync" "time" @@ -35,7 +22,6 @@ import ( "github.com/coreos/coreos-cloudinit/datasource/proc_cmdline" "github.com/coreos/coreos-cloudinit/datasource/url" "github.com/coreos/coreos-cloudinit/initialize" - "github.com/coreos/coreos-cloudinit/network" "github.com/coreos/coreos-cloudinit/pkg" "github.com/coreos/coreos-cloudinit/system" rancherConfig "github.com/rancherio/os/config" @@ -97,6 +83,7 @@ func Main() { fail = true } if fail { + fmt.Println("failed validation") os.Exit(1) } } else { @@ -151,15 +138,41 @@ func Main() { os.Exit(0) } - if err = initialize.Apply(cc, []network.InterfaceGenerator{}, env); err != nil { - log.Fatalf("Failed to apply cloud-config: %v", err) - } - if script != nil { - if err = runScript(*script, env); err != nil { - log.Fatalf("Failed to run script: %v", err) + if ds.Type() != "local-file" { + fmt.Println("can only execute local files") + } + cmdPath := reflect.ValueOf(ds).Elem().Field(0).String() + cmd := exec.Command(cmdPath) + fmt.Println("running ", cmdPath) + if err := cmd.Run(); err != nil { + fmt.Printf("Failed to run script: %v\n", err) + os.Exit(1) } } + + if &cc == nil { + log.Fatal("no config or script found") + } + + for _, user := range cc.Users { + if user.Name == "" { + continue + } + if len(user.SSHAuthorizedKeys) > 0 { + authorizeSSHKeys(user.Name, user.SSHAuthorizedKeys, env.SSHKeyName()) + } + } + + for _, file := range cc.WriteFiles { + f := system.File{File: file} + fullPath, err := system.WriteFile(&f, env.Root()) + if err != nil { + log.Fatalf("%v", err) + } + log.Printf("Wrote file %s to filesystem", fullPath) + } + } // mergeConfigs merges certain options from md (meta-data from the datasource) @@ -271,18 +284,3 @@ func selectDatasource(sources []datasource.Datasource) datasource.Datasource { return s } -// TODO(jonboulle): this should probably be refactored and moved into a different module -func runScript(script config.Script, env *initialize.Environment) error { - err := initialize.PrepWorkspace(env.Workspace()) - if err != nil { - fmt.Printf("Failed preparing workspace: %v\n", err) - return err - } - path, err := initialize.PersistScriptInWorkspace(script, env.Workspace()) - if err == nil { - var name string - name, err = system.ExecuteScript(path) - initialize.PersistUnitNameInWorkspace(name, env.Workspace()) - } - return err -} diff --git a/config/default.go b/config/default.go index 9b5061b4..c264089c 100644 --- a/config/default.go +++ b/config/default.go @@ -17,6 +17,9 @@ func NewConfig() *Config { Userdocker: UserDockerInfo{ UseTLS: true, }, + CloudInit: CloudInit{ + Datasources: []string{"file:/home/rancher/cloudconfig"}, + }, SystemContainers: []ContainerConfig{ { Id: "system-volumes", diff --git a/scripts/dockerimages/06-console b/scripts/dockerimages/06-console index 8818815e..696ab451 100644 --- a/scripts/dockerimages/06-console +++ b/scripts/dockerimages/06-console @@ -1,5 +1,6 @@ FROM base COPY scripts/dockerimages/scripts/console.sh /usr/sbin/ +COPY scripts/dockerimages/scripts/update-ssh-keys /usr/bin/ RUN sed -i 's/rancher.*/rancher:rixbL64o6zGmY:16486:0:99999:7:::/g' /etc/shadow && \ echo '## allow password less for rancher user' >> /etc/sudoers && \ echo 'rancher ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers diff --git a/scripts/dockerimages/scripts/cloud-init.sh b/scripts/dockerimages/scripts/cloud-init.sh index ce43f1e7..9b544183 100755 --- a/scripts/dockerimages/scripts/cloud-init.sh +++ b/scripts/dockerimages/scripts/cloud-init.sh @@ -2,6 +2,4 @@ set -x -e -CLOUD_CONFIG_FLAGS=$(rancherctl config get cloud_config) - -cloud-init --preinit "$CLOUD_CONFIG_FLAGS" +cloud-init diff --git a/scripts/dockerimages/scripts/update-ssh-keys b/scripts/dockerimages/scripts/update-ssh-keys new file mode 100755 index 00000000..78bc624b --- /dev/null +++ b/scripts/dockerimages/scripts/update-ssh-keys @@ -0,0 +1,13 @@ +#!/bin/bash + +USERNAME=$1 +HOME_DIR=$(grep ^$USERNAME /etc/passwd | cut -f6 -d:) + +if [ ! -d $HOME_DIR/.ssh ]; then + mkdir -p $HOME_DIR/.ssh +fi + + +if [ ! grep -q $HOME_DIR/.ssh/authorized_keys ]; then + echo "$2" >> $HOME_DIR/.ssh/authorized_keys +fi