// RestoreError makes a best effort at converting the given error // back into an error originally converted by ServerError(). If the // error could not be converted then false is returned. func RestoreError(err error) (error, bool) { err = errors.Cause(err) if apiErr, ok := err.(*params.Error); !ok { return err, false } else if apiErr == nil { return nil, true } if params.ErrCode(err) == "" { return err, false } msg := err.Error() if singleton, ok := singletonError(err); ok { return singleton, true } // TODO(ericsnow) Support the other error types handled by ServerError(). switch { case params.IsCodeUnauthorized(err): return errors.NewUnauthorized(nil, msg), true case params.IsCodeNotFound(err): // TODO(ericsnow) UnknownModelError should be handled here too. // ...by parsing msg? return errors.NewNotFound(nil, msg), true case params.IsCodeAlreadyExists(err): return errors.NewAlreadyExists(nil, msg), true case params.IsCodeNotAssigned(err): return errors.NewNotAssigned(nil, msg), true case params.IsCodeHasAssignedUnits(err): // TODO(ericsnow) Handle state.HasAssignedUnitsError here. // ...by parsing msg? return err, false case params.IsCodeNoAddressSet(err): // TODO(ericsnow) Handle isNoAddressSetError here. // ...by parsing msg? return err, false case params.IsCodeNotProvisioned(err): return errors.NewNotProvisioned(nil, msg), true case params.IsCodeUpgradeInProgress(err): // TODO(ericsnow) Handle state.UpgradeInProgressError here. // ...by parsing msg? return err, false case params.IsCodeMachineHasAttachedStorage(err): // TODO(ericsnow) Handle state.HasAttachmentsError here. // ...by parsing msg? return err, false case params.IsCodeNotSupported(err): return errors.NewNotSupported(nil, msg), true case params.IsBadRequest(err): return errors.NewBadRequest(nil, msg), true case params.IsMethodNotAllowed(err): return errors.NewMethodNotAllowed(nil, msg), true case params.ErrCode(err) == params.CodeDischargeRequired: // TODO(ericsnow) Handle DischargeRequiredError here. return err, false default: return err, false } }
func (s *URLsSuite) TestToolsMetadataURLsRegisteredFuncs(c *gc.C) { tools.RegisterToolsDataSourceFunc("id0", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id0", "betwixt/releases", utils.NoVerifySSLHostnames), nil }) tools.RegisterToolsDataSourceFunc("id1", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id1", "yoink", utils.NoVerifySSLHostnames), nil }) // overwrite the one previously registered against id1 tools.RegisterToolsDataSourceFunc("id1", func(environs.Environ) (simplestreams.DataSource, error) { // NotSupported errors do not cause GetMetadataSources to fail, // they just cause the datasource function to be ignored. return nil, errors.NewNotSupported(nil, "oyvey") }) defer tools.UnregisterToolsDataSourceFunc("id0") defer tools.UnregisterToolsDataSourceFunc("id1") env := s.env(c, "config-tools-metadata-url") sources, err := tools.GetMetadataSources(env) c.Assert(err, jc.ErrorIsNil) sstesting.AssertExpectedSources(c, sources, []string{ "config-tools-metadata-url/", "betwixt/releases/", "https://streams.canonical.com/juju/tools/", }) }
func (s *ImageMetadataSuite) TestImageMetadataURLsRegisteredFuncs(c *gc.C) { environs.RegisterImageDataSourceFunc("id0", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id0", "betwixt/releases", utils.NoVerifySSLHostnames), nil }) environs.RegisterImageDataSourceFunc("id1", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id1", "yoink", utils.NoVerifySSLHostnames), nil }) // overwrite the one previously registered against id1 environs.RegisterImageDataSourceFunc("id1", func(environs.Environ) (simplestreams.DataSource, error) { return nil, errors.NewNotSupported(nil, "oyvey") }) environs.RegisterUserImageDataSourceFunc("id2", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id2", "foobar", utils.NoVerifySSLHostnames), nil }) defer environs.UnregisterImageDataSourceFunc("id0") defer environs.UnregisterImageDataSourceFunc("id1") defer environs.UnregisterImageDataSourceFunc("id2") env := s.env(c, "config-image-metadata-url", "") sources, err := environs.ImageMetadataSources(env) c.Assert(err, jc.ErrorIsNil) sstesting.AssertExpectedSources(c, sources, []string{ "config-image-metadata-url/", "foobar/", "betwixt/releases/", "http://cloud-images.ubuntu.com/releases/", }) }
func newOpenstackStorageAdapter(environConfig *config.Config) (openstackStorage, error) { ecfg, err := providerInstance.newConfig(environConfig) if err != nil { return nil, errors.Trace(err) } client, err := authClient(ecfg) if err != nil { return nil, errors.Trace(err) } else if err := client.Authenticate(); err != nil { return nil, errors.Trace(err) } endpointUrl, err := getVolumeEndpointURL(client, ecfg.region()) if err != nil { if errors.IsNotFound(err) { return nil, errors.NewNotSupported(err, "volumes not supported") } return nil, errors.Annotate(err, "getting volume endpoint") } return &openstackStorageAdapter{ cinderClient{cinder.Basic(endpointUrl, client.TenantId(), client.Token)}, novaClient{nova.New(client)}, }, nil }
func (s *ImageMetadataSuite) TestImageMetadataURLsRegisteredFuncs(c *gc.C) { environs.RegisterImageDataSourceFunc("id0", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id0", "betwixt/releases", utils.NoVerifySSLHostnames, simplestreams.DEFAULT_CLOUD_DATA, false), nil }) environs.RegisterImageDataSourceFunc("id1", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id1", "yoink", utils.NoVerifySSLHostnames, simplestreams.SPECIFIC_CLOUD_DATA, false), nil }) // overwrite the one previously registered against id1 environs.RegisterImageDataSourceFunc("id1", func(environs.Environ) (simplestreams.DataSource, error) { return nil, errors.NewNotSupported(nil, "oyvey") }) environs.RegisterUserImageDataSourceFunc("id2", func(environs.Environ) (simplestreams.DataSource, error) { return simplestreams.NewURLDataSource("id2", "foobar", utils.NoVerifySSLHostnames, simplestreams.CUSTOM_CLOUD_DATA, false), nil }) defer environs.UnregisterImageDataSourceFunc("id0") defer environs.UnregisterImageDataSourceFunc("id1") defer environs.UnregisterImageDataSourceFunc("id2") env := s.env(c, "config-image-metadata-url", "") sources, err := environs.ImageMetadataSources(env) c.Assert(err, jc.ErrorIsNil) sstesting.AssertExpectedSources(c, sources, []sstesting.SourceDetails{ {"config-image-metadata-url/", ""}, {"foobar/", ""}, {"betwixt/releases/", ""}, {"https://streams.canonical.com/juju/images/releases/", imagemetadata.SimplestreamsImagesPublicKey}, {"http://cloud-images.ubuntu.com/releases/", imagemetadata.SimplestreamsImagesPublicKey}, }) }
// ListSpaces lists all available spaces and their associated subnets. func (api *API) ListSpaces() ([]params.Space, error) { var response params.ListSpacesResults err := api.facade.FacadeCall("ListSpaces", nil, &response) if params.IsCodeNotSupported(err) { return response.Results, errors.NewNotSupported(nil, err.Error()) } return response.Results, err }
func (s *ListSuite) TestRunWhenSpacesNotSupported(c *gc.C) { s.api.SetErrors(errors.NewNotSupported(nil, "spaces not supported")) err := s.AssertRunSpacesNotSupported(c, "cannot list spaces: spaces not supported") c.Assert(err, jc.Satisfies, errors.IsNotSupported) s.api.CheckCallNames(c, "ListSpaces", "Close") s.api.CheckCall(c, 0, "ListSpaces") }
func (s *AddSuite) TestRunWhenSpacesNotSupported(c *gc.C) { s.api.SetErrors(errors.NewNotSupported(nil, "spaces not supported")) err := s.AssertRunSpacesNotSupported(c, `cannot add space "foo": spaces not supported`, "foo", "10.1.2.0/24", ) c.Assert(err, jc.Satisfies, errors.IsNotSupported) s.api.CheckCallNames(c, "AddSpace", "Close") s.api.CheckCall(c, 0, "AddSpace", "foo", s.Strings("10.1.2.0/24"), true) }
// CreateSpace creates a new Juju network space, associating the // specified subnets with it (optional; can be empty). func (api *API) CreateSpace(name string, subnetIds []string, public bool) error { var response params.ErrorResults createSpacesParams := params.CreateSpacesParams{ Spaces: []params.CreateSpaceParams{makeCreateSpaceParams(name, subnetIds, public)}, } err := api.facade.FacadeCall("CreateSpaces", createSpacesParams, &response) if err != nil { if params.IsCodeNotSupported(err) { return errors.NewNotSupported(nil, err.Error()) } return errors.Trace(err) } return response.OneError() }
// LegacyStorage creates an Environ from the config in state and returns // its provider storage interface if it supports one. If the environment // does not support provider storage, then it will return an error // satisfying errors.IsNotSupported. func LegacyStorage(st *state.State) (storage.Storage, error) { envConfig, err := st.EnvironConfig() if err != nil { return nil, fmt.Errorf("cannot get environment config: %v", err) } env, err := New(envConfig) if err != nil { return nil, fmt.Errorf("cannot access environment: %v", err) } if env, ok := env.(EnvironStorage); ok { return env.Storage(), nil } errmsg := fmt.Sprintf("%s provider does not support provider storage", envConfig.Type()) return nil, errors.NewNotSupported(nil, errmsg) }
// Init implements Command.Init. func (c *importKeysCommand) Init(args []string) error { if len(args) == 0 { return errors.New("no ssh key id specified") } c.sshKeyIds = args for _, k := range c.sshKeyIds { if len(k) < 3 { return errors.NotValidf("%q key ID", k) } switch k[:3] { case "lp:", "gh:": default: return errors.NewNotSupported(nil, fmt.Sprintf("prefix in Key ID %q not supported, only lp: and gh: are allowed", k)) } } return nil }
func (e *Environ) getKeystoneDataSource(mu *sync.Mutex, datasource *simplestreams.DataSource, keystoneName string) (simplestreams.DataSource, error) { mu.Lock() defer mu.Unlock() if *datasource != nil { return *datasource, nil } if !e.client.IsAuthenticated() { if err := authenticateClient(e); err != nil { return nil, err } } url, err := makeServiceURL(e.client, keystoneName, nil) if err != nil { return nil, errors.NewNotSupported(err, fmt.Sprintf("cannot make service URL: %v", err)) } verify := utils.VerifySSLHostnames if !e.Config().SSLHostnameVerification() { verify = utils.NoVerifySSLHostnames } *datasource = simplestreams.NewURLDataSource("keystone catalog", url, verify, simplestreams.SPECIFIC_CLOUD_DATA, false) return *datasource, nil }
func modelFacadesOnly(facadeName, _ string) error { if !isModelFacade(facadeName) { return errors.NewNotSupported(nil, fmt.Sprintf("facade %q not supported for model API connection", facadeName)) } return nil }
// OldAgentError is returned when an api call is not supported // by the Juju agent. func OldAgentError(operation string, vers string) error { return errors.NewNotSupported( nil, fmt.Sprintf("%s not supported. Please upgrade API server to Juju %v or later", operation, vers)) }
func controllerFacadesOnly(facadeName, _ string) error { if !isControllerFacade(facadeName) { return errors.NewNotSupported(nil, fmt.Sprintf("facade %q not supported for controller API connection", facadeName)) } return nil }