func (s *StateSuite) TestEnvironConfigWithAdminSecret(c *C) { attrs := map[string]interface{}{ "name": "test", "type": "test", "authorized-keys": "i-am-a-key", "default-series": "precise", "development": true, "admin-secret": "foo", "ca-cert": testing.CACert, "ca-private-key": "", } cfg, err := config.New(attrs) c.Assert(err, IsNil) _, err = state.Initialize(state.TestingStateInfo(), cfg) c.Assert(err, ErrorMatches, "admin-secret should never be written to the state") delete(attrs, "admin-secret") cfg, err = config.New(attrs) st, err := state.Initialize(state.TestingStateInfo(), cfg) c.Assert(err, IsNil) st.Close() cfg, err = cfg.Apply(map[string]interface{}{"admin-secret": "foo"}) err = s.State.SetEnvironConfig(cfg) c.Assert(err, ErrorMatches, "admin-secret should never be written to the state") }
func (s *StateSuite) TestEnvironConfig(c *C) { initial := map[string]interface{}{ "name": "test", "type": "test", "authorized-keys": "i-am-a-key", "default-series": "precise", "development": true, "firewall-mode": "", "admin-secret": "", "ca-cert": testing.CACert, "ca-private-key": "", "ssl-hostname-verification": true, } cfg, err := config.New(initial) c.Assert(err, IsNil) st, err := state.Initialize(state.TestingStateInfo(), cfg) c.Assert(err, IsNil) st.Close() c.Assert(err, IsNil) cfg, err = s.State.EnvironConfig() c.Assert(err, IsNil) current := cfg.AllAttrs() c.Assert(current, DeepEquals, initial) current["authorized-keys"] = "i-am-a-new-key" cfg, err = config.New(current) c.Assert(err, IsNil) err = s.State.SetEnvironConfig(cfg) c.Assert(err, IsNil) cfg, err = s.State.EnvironConfig() c.Assert(err, IsNil) final := cfg.AllAttrs() c.Assert(final, DeepEquals, current) }
func (*ConfigSuite) TestValidateRejectsChangingStorageContainer(c *C) { attrs := makeAzureConfigMap(c) newConfig, err := config.New(attrs) c.Assert(err, IsNil) provider := azureEnvironProvider{} attrs["storage-container-name"] = "another name" oldConfig, err := config.New(attrs) c.Assert(err, IsNil) _, err = provider.Validate(newConfig, oldConfig) c.Check(err, ErrorMatches, ".*cannot change storage-container-name.*") }
func (*ConfigSuite) TestValidateAcceptsUnchangedConfig(c *C) { attrs := makeAzureConfigMap(c) provider := azureEnvironProvider{} oldConfig, err := config.New(attrs) c.Assert(err, IsNil) newConfig, err := config.New(attrs) c.Assert(err, IsNil) result, err := provider.Validate(newConfig, oldConfig) c.Assert(err, IsNil) c.Check(result.Name(), Equals, attrs["name"]) }
func (*ConfigSuite) TestValidateChecksConfigChanges(c *C) { provider := azureEnvironProvider{} oldAttrs := makeBaseConfigMap() oldConfig, err := config.New(oldAttrs) c.Assert(err, IsNil) newAttrs := makeBaseConfigMap() newAttrs["name"] = "different-name" newConfig, err := config.New(newAttrs) c.Assert(err, IsNil) _, err = provider.Validate(newConfig, oldConfig) c.Check(err, NotNil) }
func (*ConfigSuite) TestValidateParsesAzureConfig(c *C) { managementSubscriptionId := "subscription-id" certificate := "certificate content" storageAccountName := "account-name" storageAccountKey := "account-key" storageContainerName := "container-name" publicStorageAccountName := "public-account-name" publicStorageContainerName := "public-container-name" unknownFutureSetting := "preserved" azureConfig := map[string]interface{}{ "management-subscription-id": managementSubscriptionId, "management-certificate": certificate, "storage-account-name": storageAccountName, "storage-account-key": storageAccountKey, "storage-container-name": storageContainerName, "public-storage-account-name": publicStorageAccountName, "public-storage-container-name": publicStorageContainerName, "unknown-future-setting": unknownFutureSetting, } attrs := makeConfigMap(azureConfig) provider := azureEnvironProvider{} config, err := config.New(attrs) c.Assert(err, IsNil) azConfig, err := provider.newConfig(config) c.Assert(err, IsNil) c.Check(azConfig.Name(), Equals, attrs["name"]) c.Check(azConfig.ManagementSubscriptionId(), Equals, managementSubscriptionId) c.Check(azConfig.ManagementCertificate(), Equals, certificate) c.Check(azConfig.StorageAccountName(), Equals, storageAccountName) c.Check(azConfig.StorageAccountKey(), Equals, storageAccountKey) c.Check(azConfig.StorageContainerName(), Equals, storageContainerName) c.Check(azConfig.PublicStorageAccountName(), Equals, publicStorageAccountName) c.Check(azConfig.PublicStorageContainerName(), Equals, publicStorageContainerName) c.Check(azConfig.UnknownAttrs()["unknown-future-setting"], Equals, unknownFutureSetting) }
func (*ConfigSuite) TestFirewallMode(c *C) { for _, test := range firewallModeTests { c.Logf("test firewall mode %q", test.configFirewallMode) cfgMap := map[string]interface{}{ "name": "only", "type": "dummy", "state-server": true, "authorized-keys": "none", "ca-cert": testing.CACert, "ca-private-key": "", } if test.configFirewallMode != "" { cfgMap["firewall-mode"] = test.configFirewallMode } cfg, err := config.New(cfgMap) if err != nil { c.Assert(err, ErrorMatches, test.errorMsg) continue } env, err := environs.New(cfg) if err != nil { c.Assert(err, ErrorMatches, test.errorMsg) continue } firewallMode := env.Config().FirewallMode() c.Assert(firewallMode, Equals, test.firewallMode) } }
func (suite) TestBootstrapConfig(c *C) { defer makeFakeHome(c, "bladaam").restore() cfg, err := config.New(map[string]interface{}{ "name": "bladaam", "type": "dummy", "state-server": false, "admin-secret": "highly", "secret": "um", "authorized-keys": "i-am-a-key", "ca-cert": testing.CACert, "ca-private-key": testing.CAKey, }) c.Assert(err, IsNil) provider, err := environs.Provider(cfg.Type()) c.Assert(err, IsNil) tools := &state.Tools{ URL: "http://x", Binary: version.MustParseBinary("1.2.3-foo-bar"), } cfg1, err := environs.BootstrapConfig(provider, cfg, tools) c.Assert(err, IsNil) expect := cfg.AllAttrs() delete(expect, "secret") expect["admin-secret"] = "" expect["ca-private-key"] = "" expect["agent-version"] = "1.2.3" c.Assert(cfg1.AllAttrs(), DeepEquals, expect) }
func (s *StateSuite) TestWatchEnvironConfig(c *C) { watcher := s.State.WatchEnvironConfig() defer func() { c.Assert(watcher.Stop(), IsNil) }() for i, test := range watchEnvironConfigTests { c.Logf("test %d", i) change, err := config.New(test) c.Assert(err, IsNil) if i == 0 { st, err := state.Initialize(state.TestingStateInfo(), change) c.Assert(err, IsNil) st.Close() } else { err = s.State.SetEnvironConfig(change) c.Assert(err, IsNil) } c.Assert(err, IsNil) s.State.StartSync() select { case got, ok := <-watcher.Changes(): c.Assert(ok, Equals, true) c.Assert(got.AllAttrs(), DeepEquals, change.AllAttrs()) case <-time.After(500 * time.Millisecond): c.Fatalf("did not get change: %#v", test) } } select { case got := <-watcher.Changes(): c.Fatalf("got unexpected change: %#v", got) case <-time.After(50 * time.Millisecond): } }
func (*ConfigSuite) TestConfigAttrs(c *gc.C) { attrs := map[string]interface{}{ "type": "my-type", "name": "my-name", "authorized-keys": "my-keys", "firewall-mode": string(config.FwDefault), "admin-secret": "foo", "unknown": "my-unknown", "ca-private-key": "", "ca-cert": caCert, "ssl-hostname-verification": true, } cfg, err := config.New(attrs) c.Assert(err, gc.IsNil) // These attributes are added if not set. attrs["development"] = false attrs["default-series"] = config.DefaultSeries // Default firewall mode is instance attrs["firewall-mode"] = string(config.FwInstance) c.Assert(cfg.AllAttrs(), gc.DeepEquals, attrs) c.Assert(cfg.UnknownAttrs(), gc.DeepEquals, map[string]interface{}{"unknown": "my-unknown"}) newcfg, err := cfg.Apply(map[string]interface{}{ "name": "new-name", "new-unknown": "my-new-unknown", }) attrs["name"] = "new-name" attrs["new-unknown"] = "my-new-unknown" c.Assert(newcfg.AllAttrs(), gc.DeepEquals, attrs) }
func (createServiceAndUnit) step(c *C, ctx *context) { cfg, err := config.New(map[string]interface{}{ "name": "testenv", "type": "dummy", "default-series": "abominable", "agent-version": "1.2.3", "authorized-keys": "we-are-the-keys", "ca-cert": coretesting.CACert, "ca-private-key": "", }) c.Assert(err, IsNil) err = ctx.st.SetEnvironConfig(cfg) c.Assert(err, IsNil) sch, err := ctx.st.Charm(curl(0)) c.Assert(err, IsNil) svc, err := ctx.st.AddService("u", sch) c.Assert(err, IsNil) unit, err := svc.AddUnit() c.Assert(err, IsNil) // Assign the unit to a provisioned machine to match expected state. err = unit.AssignToNewMachine() c.Assert(err, IsNil) mid, err := unit.AssignedMachineId() c.Assert(err, IsNil) machine, err := ctx.st.Machine(mid) c.Assert(err, IsNil) err = machine.SetProvisioned("i-exist", "fake_nonce", nil) c.Assert(err, IsNil) ctx.svc = svc ctx.unit = unit }
func (*ConfigSuite) TestConfigAttrs(c *C) { attrs := map[string]interface{}{ "type": "my-type", "name": "my-name", "authorized-keys": "my-keys", "firewall-mode": string(config.FwDefault), "default-series": version.Current.Series, "admin-secret": "foo", "unknown": "my-unknown", "ca-private-key": "", "ca-cert": caCert, "ssl-hostname-verification": true, } cfg, err := config.New(attrs) c.Assert(err, IsNil) attrs["development"] = false // This attribute is added if not set. c.Assert(cfg.AllAttrs(), DeepEquals, attrs) c.Assert(cfg.UnknownAttrs(), DeepEquals, map[string]interface{}{"unknown": "my-unknown"}) newcfg, err := cfg.Apply(map[string]interface{}{ "name": "new-name", "new-unknown": "my-new-unknown", }) attrs["name"] = "new-name" attrs["new-unknown"] = "my-new-unknown" c.Assert(newcfg.AllAttrs(), DeepEquals, attrs) }
// BootstrapConfig returns a copy of the supplied configuration with // secret attributes removed. If the resulting config is not suitable // for bootstrapping an environment, an error is returned. func BootstrapConfig(cfg *config.Config) (*config.Config, error) { p, err := Provider(cfg.Type()) if err != nil { return nil, err } secrets, err := p.SecretAttrs(cfg) if err != nil { return nil, err } m := cfg.AllAttrs() for k := range secrets { delete(m, k) } // We never want to push admin-secret or the root CA private key to the cloud. delete(m, "admin-secret") m["ca-private-key"] = "" if cfg, err = config.New(m); err != nil { return nil, err } if _, ok := cfg.AgentVersion(); !ok { return nil, fmt.Errorf("environment configuration has no agent-version") } return cfg, nil }
// Run initializes state for an environment. func (c *BootstrapCommand) Run(_ *cmd.Context) error { if err := c.Conf.read("bootstrap"); err != nil { return err } cfg, err := config.New(c.EnvConfig) if err != nil { return err } // There is no entity that's created at init time. c.Conf.StateInfo.EntityName = "" st, err := state.Initialize(c.Conf.StateInfo, cfg) if err != nil { return err } defer st.Close() m, err := st.InjectMachine(state.InstanceId(c.InstanceId), state.JobManageEnviron) if err != nil { return err } if c.Conf.OldPassword != "" { if err := m.SetMongoPassword(c.Conf.OldPassword); err != nil { return err } if err := st.SetAdminMongoPassword(c.Conf.OldPassword); err != nil { return err } } return nil }
func (w *EnvironConfigWatcher) loop() (err error) { sw := w.st.watchSettings(environGlobalKey) defer sw.Stop() out := w.out out = nil cfg := &config.Config{} for { select { case <-w.st.watcher.Dead(): return watcher.MustErr(w.st.watcher) case <-w.tomb.Dying(): return tomb.ErrDying case settings, ok := <-sw.Changes(): if !ok { return watcher.MustErr(sw) } cfg, err = config.New(settings.Map()) if err == nil { out = w.out } else { out = nil } case out <- cfg: out = nil } } return nil }
func (*EnvironSuite) TestSetConfigLocksEnviron(c *C) { env := makeEnviron(c) cfg, err := config.New(makeAzureConfigMap(c)) c.Assert(err, IsNil) testing.TestLockingFunction(&env.Mutex, func() { env.SetConfig(cfg) }) }
// NewFromAttrs returns a new environment based on the provided configuration // attributes. func NewFromAttrs(attrs map[string]interface{}) (Environ, error) { cfg, err := config.New(attrs) if err != nil { return nil, err } return New(cfg) }
func mustNewConfig(m map[string]interface{}) *config.Config { cfg, err := config.New(m) if err != nil { panic(err) } return cfg }
func (st *State) EnvironConfig() (*config.Config, error) { settings, err := readSettings(st, environGlobalKey) if err != nil { return nil, err } attrs := settings.Map() return config.New(attrs) }
func makeEnviron(c *C) *azureEnviron { attrs := makeAzureConfigMap(c) cfg, err := config.New(attrs) c.Assert(err, IsNil) env, err := NewEnviron(cfg) c.Assert(err, IsNil) return env }
func (*CloudInitSuite) TestUserData(c *C) { testJujuHome := c.MkDir() defer config.SetJujuHome(config.SetJujuHome(testJujuHome)) tools := &tools.Tools{ URL: "http://foo.com/tools/juju1.2.3-linux-amd64.tgz", Binary: version.MustParseBinary("1.2.3-linux-amd64"), } envConfig, err := config.New(map[string]interface{}{ "type": "maas", "name": "foo", "default-series": "series", "authorized-keys": "keys", "ca-cert": testing.CACert, }) c.Assert(err, IsNil) cfg := &cloudinit.MachineConfig{ MachineId: "10", MachineNonce: "5432", Tools: tools, StateServerCert: []byte(testing.ServerCert), StateServerKey: []byte(testing.ServerKey), StateInfo: &state.Info{ Password: "******", CACert: []byte("CA CERT\n" + testing.CACert), }, APIInfo: &api.Info{ Password: "******", CACert: []byte("CA CERT\n" + testing.CACert), }, DataDir: environs.DataDir, Config: envConfig, StatePort: envConfig.StatePort(), APIPort: envConfig.APIPort(), StateServer: true, ProviderType: "dummy", } script1 := "script1" script2 := "script2" scripts := []string{script1, script2} result, err := environs.ComposeUserData(cfg, scripts...) c.Assert(err, IsNil) unzipped, err := utils.Gunzip(result) c.Assert(err, IsNil) config := make(map[interface{}]interface{}) err = goyaml.Unmarshal(unzipped, &config) c.Assert(err, IsNil) // Just check that the cloudinit config looks good. c.Check(config["apt_upgrade"], Equals, true) // The scripts given to userData where added as the first // commands to be run. runCmd := config["runcmd"].([]interface{}) c.Check(runCmd[0], Equals, script1) c.Check(runCmd[1], Equals, script2) }
func (s *StateSuite) TestDoubleInitialize(c *C) { m := map[string]interface{}{ "type": "dummy", "name": "lisboa", "authorized-keys": "i-am-a-key", "default-series": "precise", "development": true, "firewall-mode": "", "admin-secret": "", "ca-cert": testing.CACert, "ca-private-key": "", "ssl-hostname-verification": true, } cfg, err := config.New(m) c.Assert(err, IsNil) st, err := state.Initialize(state.TestingStateInfo(), cfg) c.Assert(err, IsNil) c.Assert(st, NotNil) env1, err := st.EnvironConfig() st.Close() // initialize again, there should be no error and the // environ config should not change. m = map[string]interface{}{ "type": "dummy", "name": "sydney", "authorized-keys": "i-am-not-an-animal", "default-series": "xanadu", "development": false, "firewall-mode": "", "admin-secret": "", "ca-cert": testing.CACert, "ca-private-key": "", "ssl-hostname-verification": false, } cfg, err = config.New(m) c.Assert(err, IsNil) st, err = state.Initialize(state.TestingStateInfo(), cfg) c.Assert(err, IsNil) c.Assert(st, NotNil) env2, err := st.EnvironConfig() st.Close() c.Assert(env1.AllAttrs(), DeepEquals, env2.AllAttrs()) }
func (*configSuite) TestChecksLocationIsRequired(c *C) { attrs := makeAzureConfigMap(c) attrs["location"] = "" provider := azureEnvironProvider{} newConfig, err := config.New(attrs) c.Assert(err, IsNil) _, err = provider.Validate(newConfig, nil) c.Check(err, ErrorMatches, ".*environment has no location.*") }
func newTestConfig(c *gc.C, explicit attrs) *config.Config { final := attrs{"type": "my-type", "name": "my-name"} for key, value := range explicit { final[key] = value } result, err := config.New(final) c.Assert(err, gc.IsNil) return result }
func (*ConfigSuite) TestChecksPublicStorageContainerNameCannotBeDefinedAlone(c *C) { attrs := makeAzureConfigMap(c) attrs["public-storage-account-name"] = "" provider := azureEnvironProvider{} newConfig, err := config.New(attrs) c.Assert(err, IsNil) _, err = provider.Validate(newConfig, nil) c.Check(err, ErrorMatches, ".*both or none of them.*") }
// makeEnviron creates a fake azureEnviron with arbitrary configuration. func makeEnviron(c *C) *azureEnviron { attrs := makeAzureConfigMap(c) cfg, err := config.New(attrs) c.Assert(err, IsNil) env, err := NewEnviron(cfg) c.Assert(err, IsNil) // Prevent the test from trying to query for a storage-account key. env.storageAccountKey = "fake-storage-account-key" return env }
func (*EnvironSuite) TestPublicStorageReturnsEmptyStorageIfNoInfo(c *C) { attrs := makeAzureConfigMap(c) attrs["public-storage-container-name"] = "" attrs["public-storage-account-name"] = "" cfg, err := config.New(attrs) c.Assert(err, IsNil) env, err := NewEnviron(cfg) c.Assert(err, IsNil) c.Check(env.PublicStorage(), Equals, environs.EmptyStorage) }
// Run initializes state for an environment. func (c *BootstrapCommand) Run(_ *cmd.Context) error { if err := c.Conf.read("bootstrap"); err != nil { return err } cfg, err := config.New(c.EnvConfig) if err != nil { return err } // There is no entity that's created at init time. c.Conf.StateInfo.Tag = "" st, err := state.Initialize(c.Conf.StateInfo, cfg, state.DefaultDialOpts()) if err != nil { return err } defer st.Close() if err := environs.BootstrapUsers(st, cfg, c.Conf.OldPassword); err != nil { return err } // TODO(fwereade): we need to be able to customize machine jobs, // not just hardcode these values; in particular, JobHostUnits // on a machine, like this one, that is running JobManageEnviron // (not to mention the actual state server itself...) will allow // a malicious or compromised unit to trivially access to the // user's environment credentials. However, given that this point // is currently moot (see Upgrader in this package), the pseudo- // local provider mode (in which everything is deployed with // `--to 0`) offers enough value to enough people that // JobHostUnits is currently always enabled. This will one day // have to change, but it's strictly less important than fixing // Upgrader, and it's a capability we'll always want to have // available for the aforementioned use case. jobs := []state.MachineJob{ state.JobManageEnviron, state.JobManageState, state.JobHostUnits, } data, err := ioutil.ReadFile(providerStateURLFile) if err != nil { return fmt.Errorf("cannot read provider-state-url file: %v", err) } stateInfoURL := strings.Split(string(data), "\n")[0] bsState, err := environs.LoadStateFromURL(stateInfoURL) if err != nil { return fmt.Errorf("cannot load state from URL %q (read from %q): %v", stateInfoURL, providerStateURLFile, err) } instId := bsState.StateInstances[0] var characteristics instance.HardwareCharacteristics if len(bsState.Characteristics) > 0 { characteristics = bsState.Characteristics[0] } return environs.ConfigureBootstrapMachine(st, c.Constraints, c.Conf.DataDir, jobs, instance.Id(instId), characteristics) }
func (s *agentSuite) proposeVersion(c *C, vers version.Number, development bool) { cfg, err := s.State.EnvironConfig() c.Assert(err, IsNil) attrs := cfg.AllAttrs() attrs["agent-version"] = vers.String() attrs["development"] = development newCfg, err := config.New(attrs) c.Assert(err, IsNil) err = s.State.SetEnvironConfig(newCfg) c.Assert(err, IsNil) }
// ReadEnvironsBytes parses the contents of an environments.yaml file // and returns its representation. An environment with an unknown type // will only generate an error when New is called for that environment. // Attributes for environments with known types are checked. func ReadEnvironsBytes(data []byte) (*Environs, error) { var raw struct { Default string Environments map[string]map[string]interface{} } err := goyaml.Unmarshal(data, &raw) if err != nil { return nil, err } if raw.Default != "" && raw.Environments[raw.Default] == nil { return nil, fmt.Errorf("default environment %q does not exist", raw.Default) } if raw.Default == "" { // If there's a single environment, then we get the default // automatically. if len(raw.Environments) == 1 { for name := range raw.Environments { raw.Default = name break } } } environs := make(map[string]environ) for name, attrs := range raw.Environments { kind, _ := attrs["type"].(string) if kind == "" { environs[name] = environ{ err: fmt.Errorf("environment %q has no type", name), } continue } p := providers[kind] if p == nil { environs[name] = environ{ err: fmt.Errorf("environment %q has an unknown provider type %q", name, kind), } continue } // store the name of the this environment in the config itself // so that providers can see it. attrs["name"] = name cfg, err := config.New(attrs) if err != nil { environs[name] = environ{ err: fmt.Errorf("error parsing environment %q: %v", name, err), } continue } environs[name] = environ{config: cfg} } return &Environs{raw.Default, environs}, nil }