// NewConn returns a new Conn that uses the // given environment. The environment must have already // been bootstrapped. func NewConn(environ environs.Environ) (*Conn, error) { info, _, err := environ.StateInfo() if err != nil { return nil, err } password := environ.Config().AdminSecret() if password == "" { return nil, fmt.Errorf("cannot connect without admin-secret") } err = environs.CheckEnvironment(environ) if err != nil { return nil, err } info.Password = password opts := state.DefaultDialOpts() st, err := state.Open(info, opts) if errors.IsUnauthorizedError(err) { log.Noticef("juju: authorization error while connecting to state server; retrying") // We can't connect with the administrator password,; // perhaps this was the first connection and the // password has not been changed yet. info.Password = utils.PasswordHash(password) // We try for a while because we might succeed in // connecting to mongo before the state has been // initialized and the initial password set. for a := redialStrategy.Start(); a.Next(); { st, err = state.Open(info, opts) if !errors.IsUnauthorizedError(err) { break } } if err != nil { return nil, err } if err := st.SetAdminMongoPassword(password); err != nil { return nil, err } } else if err != nil { return nil, err } conn := &Conn{ Environ: environ, State: st, } if err := conn.updateSecrets(); err != nil { conn.Close() return nil, fmt.Errorf("unable to push secrets: %v", err) } return conn, nil }
func (s *checkEnvironmentSuite) TestCheckEnvironment(c *C) { defer testing.MakeFakeHome(c, checkEnv, "existing").Restore() environ, err := environs.NewFromName("test") c.Assert(err, IsNil) // VerifyStorage is sufficient for our tests and much simpler // than Bootstrap which calls it. storage := environ.Storage() err = environs.VerifyStorage(storage) c.Assert(err, IsNil) err = environs.CheckEnvironment(environ) c.Assert(err, IsNil) }
func (s *checkEnvironmentSuite) TestCheckEnvironmentBadContent(c *C) { defer testing.MakeFakeHome(c, checkEnv, "existing").Restore() environ, err := environs.NewFromName("test") c.Assert(err, IsNil) // We mock a bad (eg. from a Python-juju environment) bootstrap-verify. storage := environ.Storage() content := "bad verification content" reader := strings.NewReader(content) err = storage.Put("bootstrap-verify", reader, int64(len(content))) c.Assert(err, IsNil) // When the bootstrap-verify file contains unexpected content, // we get an InvalidEnvironmentError. err = environs.CheckEnvironment(environ) c.Assert(err, Equals, environs.InvalidEnvironmentError) }
func (s *checkEnvironmentSuite) TestCheckEnvironmentGetFails(c *C) { defer testing.MakeFakeHome(c, checkEnv, "existing").Restore() environ, err := environs.NewFromName("test") c.Assert(err, IsNil) // VerifyStorage is sufficient for our tests and much simpler // than Bootstrap which calls it. storage := environ.Storage() err = environs.VerifyStorage(storage) c.Assert(err, IsNil) // When fetching the verification file from storage fails, // we get an InvalidEnvironmentError. someError := errors.Unauthorizedf("you shall not pass") dummy.Poison(storage, "bootstrap-verify", someError) err = environs.CheckEnvironment(environ) c.Assert(err, Equals, someError) }
func (s *checkEnvironmentSuite) TestCheckEnvironmentFileNotFound(c *C) { defer testing.MakeFakeHome(c, checkEnv, "existing").Restore() environ, err := environs.NewFromName("test") c.Assert(err, IsNil) // VerifyStorage is sufficient for our tests and much simpler // than Bootstrap which calls it. storage := environ.Storage() err = environs.VerifyStorage(storage) c.Assert(err, IsNil) // When the bootstrap-verify file does not exist, it still believes // the environment is a juju-core one because earlier versions // did not create that file. err = storage.Remove("bootstrap-verify") c.Assert(err, IsNil) err = environs.CheckEnvironment(environ) c.Assert(err, IsNil) }