// loginRequest forms a LoginRequest from the information // in the given HTTP request. func (ctxt *httpContext) loginRequest(r *http.Request) (params.LoginRequest, error) { authHeader := r.Header.Get("Authorization") if authHeader == "" { // No authorization header implies an attempt // to login with macaroon authentication. return params.LoginRequest{ Macaroons: httpbakery.RequestMacaroons(r), }, nil } parts := strings.Fields(authHeader) if len(parts) != 2 || parts[0] != "Basic" { // Invalid header format or no header provided. return params.LoginRequest{}, errors.New("invalid request format") } // Challenge is a base64-encoded "tag:pass" string. // See RFC 2617, Section 2. challenge, err := base64.StdEncoding.DecodeString(parts[1]) if err != nil { return params.LoginRequest{}, errors.New("invalid request format") } tagPass := strings.SplitN(string(challenge), ":", 2) if len(tagPass) != 2 { return params.LoginRequest{}, errors.New("invalid request format") } // Ensure that a sensible tag was passed. _, err = names.ParseTag(tagPass[0]) if err != nil { return params.LoginRequest{}, errors.Trace(common.ErrBadCreds) } return params.LoginRequest{ AuthTag: tagPass[0], Credentials: tagPass[1], Nonce: r.Header.Get(params.MachineNonceHeader), }, nil }
// guiVersion retrieves the GUI version from the juju-gui-* directory included // in the bz2 archive at the given path. func guiVersion(path string) (version.Number, error) { var number version.Number f, err := os.Open(path) if err != nil { return number, errors.Annotate(err, "cannot open Juju GUI archive") } defer f.Close() prefix := "jujugui-" r := tar.NewReader(bzip2.NewReader(f)) for { hdr, err := r.Next() if err == io.EOF { break } if err != nil { return number, errors.New("cannot read Juju GUI archive") } info := hdr.FileInfo() if !info.IsDir() || !strings.HasPrefix(hdr.Name, prefix) { continue } n := info.Name()[len(prefix):] number, err = version.Parse(n) if err != nil { return number, errors.Errorf("cannot parse version %q", n) } return number, nil } return number, errors.New("cannot find Juju GUI version") }
// ExecRestrictedSQL implements SQLHelper interface. // This is used for executing some restricted sql statements. func (s *session) ExecRestrictedSQL(ctx context.Context, sql string) (rset.Recordset, error) { if ctx.Value(&sqlexec.RestrictedSQLExecutorKeyType{}) != nil { // We do not support run this function concurrently. // TODO: Maybe we should remove this restriction latter. return nil, errors.New("Should not call ExecRestrictedSQL concurrently.") } statements, err := Compile(ctx, sql) if err != nil { log.Errorf("Compile %s with error: %v", sql, err) return nil, errors.Trace(err) } if len(statements) != 1 { log.Errorf("ExecRestrictedSQL only executes one statement. Too many/few statement in %s", sql) return nil, errors.New("Wrong number of statement.") } st := statements[0] // Check statement for some restriction // For example only support DML on system meta table. // TODO: Add more restrictions. log.Debugf("Executing %s [%s]", st.OriginText(), sql) ctx.SetValue(&sqlexec.RestrictedSQLExecutorKeyType{}, true) defer ctx.ClearValue(&sqlexec.RestrictedSQLExecutorKeyType{}) rs, err := st.Exec(ctx) return rs, errors.Trace(err) }
func (s *InstancePollerSuite) TestSetInstanceStatusFailure(c *gc.C) { s.st.SetErrors( errors.New("pow!"), // m1 := FindEntity("1") nil, // m2 := FindEntity("2") errors.New("FAIL"), // m2.SetInstanceStatus() errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved) ) s.st.SetMachineInfo(c, machineInfo{id: "1", instanceStatus: statusInfo("foo")}) s.st.SetMachineInfo(c, machineInfo{id: "2", instanceStatus: statusInfo("")}) result, err := s.api.SetInstanceStatus(params.SetStatus{ Entities: []params.EntityStatusArgs{ {Tag: "machine-1", Status: "new"}, {Tag: "machine-2", Status: "invalid"}, {Tag: "machine-3", Status: ""}, }}, ) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, s.machineErrorResults) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckFindEntityCall(c, 1, "2") now := s.clock.Now() s.st.CheckCall(c, 2, "SetInstanceStatus", status.StatusInfo{Status: "invalid", Since: &now}) s.st.CheckFindEntityCall(c, 3, "3") }
// rsyslogServerCerts generates new certificates for RsyslogConfigHandler // using the provider caCert and caKey. This is used during the setup of the // rsyslog worker as well as when handling any changes to the rsyslog configuration, // usually adding and removing of state machines through ensure-availability. func (h *RsyslogConfigHandler) rsyslogServerCerts(caCert, caKey string) (string, string, error) { if caCert == "" { return "", "", errors.New("CACert is not set") } if caKey == "" { return "", "", errors.New("CAKey is not set") } expiry := time.Now().UTC().AddDate(10, 0, 0) // Add rsyslog servers in the subjectAltName so we can // successfully validate when connectiong via SSL hosts, err := h.rsyslogHosts() if err != nil { return "", "", err } // Add local IPs to SAN. When connecting via IP address, // the client will validate the server against any IP in // the subjectAltName. We add all local ips to make sure // this does not cause an error ips, err := localIPS() if err != nil { return "", "", err } hosts = append(hosts, ips...) return cert.NewServer(caCert, caKey, expiry, hosts) }
func (s *InstancePollerSuite) TestLifeFailure(c *gc.C) { s.st.SetErrors( errors.New("pow!"), // m1 := FindEntity("1"); Life not called nil, // m2 := FindEntity("2") errors.New("FAIL"), // m2.Life() - unused errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved) ) s.st.SetMachineInfo(c, machineInfo{id: "1", life: state.Alive}) s.st.SetMachineInfo(c, machineInfo{id: "2", life: state.Dead}) s.st.SetMachineInfo(c, machineInfo{id: "3", life: state.Dying}) result, err := s.api.Life(s.machineEntities) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.LifeResults{ Results: []params.LifeResult{ {Error: apiservertesting.ServerError("pow!")}, {Life: params.Dead}, {Error: apiservertesting.NotProvisionedError("42")}, }}, ) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckFindEntityCall(c, 1, "2") s.st.CheckCall(c, 2, "Life") s.st.CheckFindEntityCall(c, 3, "3") }
func (s *InstancePollerSuite) TestProviderAddressesFailure(c *gc.C) { s.st.SetErrors( errors.New("pow!"), // m1 := FindEntity("1") nil, // m2 := FindEntity("2") errors.New("FAIL"), // m2.ProviderAddresses()- unused errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved) ) s.st.SetMachineInfo(c, machineInfo{id: "1"}) s.st.SetMachineInfo(c, machineInfo{id: "2"}) result, err := s.api.ProviderAddresses(s.machineEntities) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.MachineAddressesResults{ Results: []params.MachineAddressesResult{ {Error: apiservertesting.ServerError("pow!")}, {Addresses: nil}, {Error: apiservertesting.NotProvisionedError("42")}, }}, ) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckFindEntityCall(c, 1, "2") s.st.CheckCall(c, 2, "ProviderAddresses") s.st.CheckFindEntityCall(c, 3, "3") }
func (s *EngineSuite) TestIsFatal(c *gc.C) { // Start an engine that pays attention to fatal errors. fatalError := errors.New("KABOOM") s.stopEngine(c) s.startEngine(c, func(err error) bool { return err == fatalError }) // Start two independent workers. mh1 := newManifoldHarness() err := s.engine.Install("some-task", mh1.Manifold()) c.Assert(err, jc.ErrorIsNil) mh1.AssertOneStart(c) mh2 := newManifoldHarness() err = s.engine.Install("other-task", mh2.Manifold()) c.Assert(err, jc.ErrorIsNil) mh2.AssertOneStart(c) // Bounce one worker with Just Some Error; check that worker bounces. mh1.InjectError(c, errors.New("splort")) mh1.AssertOneStart(c) mh2.AssertNoStart(c) // Bounce another worker with the fatal error; check the engine exits with // the right error. mh2.InjectError(c, fatalError) mh1.AssertNoStart(c) mh2.AssertNoStart(c) err = worker.Stop(s.engine) c.Assert(err, gc.Equals, fatalError) // Clear out s.engine -- lest TearDownTest freak out about the error. s.engine = nil }
// effectiveMachineTemplate verifies that the given template is // valid and combines it with values from the state // to produce a resulting template that more accurately // represents the data that will be inserted into the state. func (st *State) effectiveMachineTemplate(p MachineTemplate, allowController bool) (tmpl MachineTemplate, err error) { // First check for obvious errors. if p.Series == "" { return tmpl, errors.New("no series specified") } if p.InstanceId != "" { if p.Nonce == "" { return tmpl, errors.New("cannot add a machine with an instance id and no nonce") } } else if p.Nonce != "" { return tmpl, errors.New("cannot specify a nonce without an instance id") } p.Constraints, err = st.resolveMachineConstraints(p.Constraints) if err != nil { return tmpl, err } if len(p.Jobs) == 0 { return tmpl, errors.New("no jobs specified") } jset := make(map[MachineJob]bool) for _, j := range p.Jobs { if jset[j] { return MachineTemplate{}, errors.Errorf("duplicate job: %s", j) } jset[j] = true } if jset[JobManageModel] { if !allowController { return tmpl, errControllerNotAllowed } } return p, nil }
// archiveVersion retrieves the GUI version from the juju-gui-* directory // included in the given tar.bz2 archive reader. func archiveVersion(r io.Reader) (version.Number, error) { var vers version.Number prefix := "jujugui-" tr := tar.NewReader(bzip2.NewReader(r)) for { hdr, err := tr.Next() if err == io.EOF { break } if err != nil { return vers, errors.New("cannot read Juju GUI archive") } info := hdr.FileInfo() if !info.IsDir() || !strings.HasPrefix(hdr.Name, prefix) { continue } n := filepath.Dir(hdr.Name)[len(prefix):] vers, err = version.Parse(n) if err != nil { return vers, errors.Errorf("invalid version %q in archive", n) } return vers, nil } return vers, errors.New("cannot find Juju GUI version in archive") }
func (s *actionsSuite) TestFinishActions(c *gc.C) { args := params.ActionExecutionResults{ []params.ActionExecutionResult{ {ActionTag: "success", Status: string(state.ActionCompleted)}, {ActionTag: "notfound"}, {ActionTag: "convertFail", Status: "failStatus"}, {ActionTag: "finishFail", Status: string(state.ActionCancelled)}, }, } expectErr := errors.New("explosivo") actionFn := makeGetActionByTagString(map[string]state.Action{ "success": fakeAction{}, "convertFail": fakeAction{}, "finishFail": fakeAction{finishErr: expectErr}, }) results := common.FinishActions(args, actionFn) c.Assert(results, jc.DeepEquals, params.ErrorResults{ []params.ErrorResult{ {}, {common.ServerError(actionNotFoundErr)}, {common.ServerError(errors.New("unrecognized action status 'failStatus'"))}, {common.ServerError(expectErr)}, }, }) }
// validate returns an error if the state violates expectations. func (st State) validate() (err error) { defer errors.DeferredAnnotatef(&err, "invalid operation state") hasHook := st.Hook != nil hasActionId := st.ActionId != nil hasCharm := st.CharmURL != nil switch st.Kind { case Install: if st.Installed { return errors.New("unexpected hook info with Kind Install") } fallthrough case Upgrade: switch { case !hasCharm: return errors.New("missing charm URL") case hasActionId: return errors.New("unexpected action id") } case RunAction: switch { case !hasActionId: return errors.New("missing action id") case hasCharm: return errors.New("unexpected charm URL") } case RunHook: switch { case !hasHook: return errors.New("missing hook info with Kind RunHook") case hasCharm: return errors.New("unexpected charm URL") case hasActionId: return errors.New("unexpected action id") } case Continue: // TODO(jw4) LP-1438489 // ModeContinue should no longer have a Hook, but until the upgrade is // fixed we can't fail the validation if it does. if hasHook { logger.Errorf("unexpected hook info with Kind Continue") } switch { case hasCharm: return errors.New("unexpected charm URL") case hasActionId: return errors.New("unexpected action id") } default: return errors.Errorf("unknown operation %q", st.Kind) } switch st.Step { case Queued, Pending, Done: default: return errors.Errorf("unknown operation step %q", st.Step) } if hasHook { return st.Hook.Validate() } return nil }
func (s *stubSuite) TestSetErrorMixed(c *gc.C) { err1 := errors.New("<failure 1>") err2 := errors.New("<failure 2>") s.stub.SetErrors(nil, err1, nil, err2) s.stub.CheckErrors(c, nil, err1, nil, err2) }
func (s *stubSuite) TestSetErrorsMultiple(c *gc.C) { err1 := errors.New("<failure 1>") err2 := errors.New("<failure 2>") s.stub.SetErrors(err1, err2) s.stub.CheckErrors(c, err1, err2) }
// NewSSHStorage creates a new SSHStorage, connected to the // specified host, managing state under the specified remote path. func NewSSHStorage(params NewSSHStorageParams) (*SSHStorage, error) { if params.StorageDir == "" { return nil, errors.New("storagedir must be specified and non-empty") } if params.TmpDir == "" { return nil, errors.New("tmpdir must be specified and non-empty") } script := fmt.Sprintf( "install -d -g $SUDO_GID -o $SUDO_UID %s %s", utils.ShQuote(params.StorageDir), utils.ShQuote(params.TmpDir), ) cmd := sshCommand(params.Host, "sudo", "-n", "/bin/bash") var stderr bytes.Buffer cmd.Stderr = &stderr cmd.Stdin = strings.NewReader(script) if err := cmd.Run(); err != nil { err = fmt.Errorf("failed to create storage dir: %v (%v)", err, strings.TrimSpace(stderr.String())) return nil, err } // We could use sftp, but then we'd be at the mercy of // sftp's output messages for checking errors. Instead, // we execute an interactive bash shell. cmd = sshCommand(params.Host, "bash") stdin, err := cmd.StdinPipe() if err != nil { return nil, err } stdout, err := cmd.StdoutPipe() if err != nil { stdin.Close() return nil, err } // Combine stdout and stderr, so we can easily // get at catastrophic failure messages. cmd.Stderr = cmd.Stdout stor := &SSHStorage{ host: params.Host, remotepath: params.StorageDir, tmpdir: params.TmpDir, cmd: cmd, stdin: stdin, stdout: stdout, scanner: bufio.NewScanner(stdout), } cmd.Start() // Verify we have write permissions. _, err = stor.runf(flockExclusive, "touch %s", utils.ShQuote(params.StorageDir)) if err != nil { stdin.Close() stdout.Close() cmd.Wait() return nil, err } return stor, nil }
func (c *MigrateCommand) Init(args []string) error { if len(args) == 0 { return errors.New("missing operation") } c.operation, args = args[0], args[1:] switch c.operation { case "export": if len(args) == 0 { return errors.New("missing model uuid") } c.modelUUID, args = args[0], args[1:] case "import": if len(args) == 0 { return errors.New("missing yaml filename") } c.filename, args = args[0], args[1:] default: return errors.Errorf("unknown operation %q", c.operation) } if !names.IsValidMachine(c.machineId) { return errors.Errorf("%q is not a valid machine id", c.machineId) } c.machineTag = names.NewMachineTag(c.machineId) return cmd.CheckEmpty(args) }
func (s *ModelConfigSuite) TestAdditionalValidation(c *gc.C) { updateAttrs := map[string]interface{}{"logging-config": "juju=ERROR"} configValidator1 := func(updateAttrs map[string]interface{}, removeAttrs []string, oldConfig *config.Config) error { c.Assert(updateAttrs, jc.DeepEquals, map[string]interface{}{"logging-config": "juju=ERROR"}) if lc, found := updateAttrs["logging-config"]; found && lc != "" { return errors.New("cannot change logging-config") } return nil } removeAttrs := []string{"some-attr"} configValidator2 := func(updateAttrs map[string]interface{}, removeAttrs []string, oldConfig *config.Config) error { c.Assert(removeAttrs, jc.DeepEquals, []string{"some-attr"}) for _, i := range removeAttrs { if i == "some-attr" { return errors.New("cannot remove some-attr") } } return nil } configValidator3 := func(updateAttrs map[string]interface{}, removeAttrs []string, oldConfig *config.Config) error { return nil } err := s.State.UpdateModelConfig(updateAttrs, nil, configValidator1) c.Assert(err, gc.ErrorMatches, "cannot change logging-config") err = s.State.UpdateModelConfig(nil, removeAttrs, configValidator2) c.Assert(err, gc.ErrorMatches, "cannot remove some-attr") err = s.State.UpdateModelConfig(updateAttrs, nil, configValidator3) c.Assert(err, jc.ErrorIsNil) }
// handleExtraArgs handles the case where too many args were supplied. func (c *defaultsCommand) handleExtraArgs(args []string) error { resetSpecified := c.resetKeys != nil regionSpecified := c.regionName != "" numArgs := len(args) // if we have a key=value pair here then something is wrong because the // last positional arg is not one. We assume the user intended to get a // value after setting them. for _, arg := range args { if strings.Contains(arg, "=") { return errors.New("cannot set and retrieve default values simultaneously") } } if !regionSpecified { if resetSpecified { if numArgs == 2 { // It makes no sense to supply a positional arg that isn't a // region if we are resetting a region, so we must have gotten // an invalid region. return errors.Errorf("invalid region specified: %q", args[0]) } } if !resetSpecified { // If we land here it is because there are extraneous positional // args. return errors.New("can only retrieve defaults for one key or all") } } return errors.New("invalid input") }
func (s *InstancePollerSuite) TestInstanceIdFailure(c *gc.C) { s.st.SetErrors( errors.New("pow!"), // m1 := FindEntity("1"); InstanceId not called nil, // m2 := FindEntity("2") errors.New("FAIL"), // m2.InstanceId() errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved) ) s.st.SetMachineInfo(c, machineInfo{id: "1", instanceId: ""}) s.st.SetMachineInfo(c, machineInfo{id: "2", instanceId: "i-bar"}) result, err := s.api.InstanceId(s.machineEntities) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.StringResults{ Results: []params.StringResult{ {Error: apiservertesting.ServerError("pow!")}, {Error: apiservertesting.ServerError("FAIL")}, {Error: apiservertesting.NotProvisionedError("42")}, }}, ) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckFindEntityCall(c, 1, "2") s.st.CheckCall(c, 2, "InstanceId") s.st.CheckFindEntityCall(c, 3, "3") }
// See http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_sleep func builtinSleep(args []types.Datum, ctx context.Context) (d types.Datum, err error) { if ctx == nil { return d, errors.Errorf("Missing context when evalue builtin") } sessVars := variable.GetSessionVars(ctx) if args[0].IsNull() { if sessVars.StrictSQLMode { return d, errors.New("Incorrect arguments to sleep.") } d.SetInt64(0) return } // processing argument is negative zero := types.NewIntDatum(0) ret, err := args[0].CompareDatum(zero) if err != nil { return d, errors.Trace(err) } if ret == -1 { if sessVars.StrictSQLMode { return d, errors.New("Incorrect arguments to sleep.") } d.SetInt64(0) return } // TODO: consider it's interrupted using KILL QUERY from other session, or // interrupted by time out. duration := time.Duration(args[0].GetFloat64() * float64(time.Second.Nanoseconds())) time.Sleep(duration) d.SetInt64(0) return }
func (s *InstancePollerSuite) TestSetProviderAddressesFailure(c *gc.C) { s.st.SetErrors( errors.New("pow!"), // m1 := FindEntity("1") nil, // m2 := FindEntity("2") errors.New("FAIL"), // m2.SetProviderAddresses() errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved) ) oldAddrs := network.NewAddresses("0.1.2.3", "127.0.0.1", "8.8.8.8") newAddrs := network.NewAddresses("1.2.3.4", "8.4.4.8", "2001:db8::") s.st.SetMachineInfo(c, machineInfo{id: "1", providerAddresses: oldAddrs}) s.st.SetMachineInfo(c, machineInfo{id: "2", providerAddresses: nil}) result, err := s.api.SetProviderAddresses(params.SetMachinesAddresses{ MachineAddresses: []params.MachineAddresses{ {Tag: "machine-1"}, {Tag: "machine-2", Addresses: params.FromNetworkAddresses(newAddrs...)}, {Tag: "machine-3"}, }}, ) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, s.machineErrorResults) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckFindEntityCall(c, 1, "2") s.st.CheckSetProviderAddressesCall(c, 2, newAddrs) s.st.CheckFindEntityCall(c, 3, "3") // Ensure machine 2 wasn't updated. machine, err := s.st.Machine("2") c.Assert(err, jc.ErrorIsNil) c.Assert(machine.ProviderAddresses(), gc.HasLen, 0) }
func (w *rpcWorker) getTSFromRemote(conn *bufio.ReadWriter, n int) (pdpb.Timestamp, error) { var timestampHigh = pdpb.Timestamp{} req := &pdpb.Request{ Header: &pdpb.RequestHeader{ Uuid: uuid.NewV4().Bytes(), ClusterId: w.clusterID, }, CmdType: pdpb.CommandType_Tso, Tso: &pdpb.TsoRequest{ Count: uint32(n), }, } resp, err := w.callRPC(conn, req) if err != nil { return timestampHigh, errors.Trace(err) } if resp.GetTso() == nil { return timestampHigh, errors.New("[pd] tso filed in rpc response not set") } timestampHigh = resp.GetTso().GetTimestamp() if resp.GetTso().GetCount() != uint32(n) { return timestampHigh, errors.New("[pd] tso length in rpc response is incorrect") } return timestampHigh, nil }
func (s *InstancePollerSuite) TestAreManuallyProvisionedFailure(c *gc.C) { s.st.SetErrors( errors.New("pow!"), // m1 := FindEntity("1") nil, // m2 := FindEntity("2") errors.New("FAIL"), // m2.IsManual() errors.NotProvisionedf("machine 42"), // FindEntity("3") (ensure wrapping is preserved) ) s.st.SetMachineInfo(c, machineInfo{id: "1", isManual: true}) s.st.SetMachineInfo(c, machineInfo{id: "2", isManual: false}) result, err := s.api.AreManuallyProvisioned(s.machineEntities) c.Assert(err, jc.ErrorIsNil) c.Assert(result, jc.DeepEquals, params.BoolResults{ Results: []params.BoolResult{ {Error: apiservertesting.ServerError("pow!")}, {Error: apiservertesting.ServerError("FAIL")}, {Error: apiservertesting.NotProvisionedError("42")}, }}, ) s.st.CheckFindEntityCall(c, 0, "1") s.st.CheckFindEntityCall(c, 1, "2") s.st.CheckCall(c, 2, "IsManual") s.st.CheckFindEntityCall(c, 3, "3") }
// SetMinUnits changes the number of minimum units required by the service. func (s *Service) SetMinUnits(minUnits int) (err error) { defer errors.Maskf(&err, "cannot set minimum units for service %q", s) defer func() { if err == nil { s.doc.MinUnits = minUnits } }() if minUnits < 0 { return errors.New("cannot set a negative minimum number of units") } service := &Service{st: s.st, doc: s.doc} // Removing the document never fails. Racing clients trying to create the // document generate one failure, but the second attempt should succeed. // If one client tries to update the document, and a racing client removes // it, the former should be able to re-create the document in the second // attempt. If the referred-to service advanced its life cycle to a not // alive state, an error is returned after the first failing attempt. buildTxn := func(attempt int) ([]txn.Op, error) { if attempt > 0 { if err := service.Refresh(); err != nil { return nil, err } } if service.doc.Life != Alive { return nil, errors.New("service is no longer alive") } if minUnits == service.doc.MinUnits { return nil, statetxn.ErrNoOperations } return setMinUnitsOps(service, minUnits), nil } return s.st.run(buildTxn) }
// Remove removes an existing IP address. Trying to remove a missing // address is not an error. func (i *IPAddress) Remove() (err error) { defer errors.DeferredAnnotatef(&err, "cannot remove IP address %q", i) if i.doc.Life != Dead { return errors.New("IP address is not dead") } buildTxn := func(attempt int) ([]txn.Op, error) { if attempt > 0 { if err := i.Refresh(); errors.IsNotFound(err) { return nil, jujutxn.ErrNoOperations } else if err != nil { return nil, err } if i.Life() != Dead { return nil, errors.New("address is not dead") } } return []txn.Op{{ C: ipaddressesC, Id: i.doc.DocID, Assert: isDeadDoc, Remove: true, }}, nil } return i.st.run(buildTxn) }
// APIInfo returns an api.Info for the environment. The result is populated // with addresses and CA certificate, but no tag or password. func APIInfo(env Environ) (*api.Info, error) { instanceIds, err := env.ControllerInstances() if err != nil { return nil, err } logger.Debugf("ControllerInstances returned: %v", instanceIds) addrs, err := waitAnyInstanceAddresses(env, instanceIds) if err != nil { return nil, err } config := env.Config() cert, hasCert := config.CACert() if !hasCert { return nil, errors.New("config has no CACert") } apiPort := config.APIPort() apiAddrs := network.HostPortsToStrings( network.AddressesWithPort(addrs, apiPort), ) uuid, uuidSet := config.UUID() if !uuidSet { return nil, errors.New("config has no UUID") } modelTag := names.NewModelTag(uuid) apiInfo := &api.Info{Addrs: apiAddrs, CACert: cert, ModelTag: modelTag} return apiInfo, nil }
func (mi *maas1Instance) zone() (string, error) { // TODO (anastasiamac 2016-03-31) // This code is needed until gomaasapi testing code is // updated to align with MAAS. // Currently, "zone" property is still treated as field // by gomaasi infrastructure and is searched for // using matchField(node, "zone", zoneName) instead of // getMap. // @see gomaasapi/testservice.go#findFreeNode // bug https://bugs.launchpad.net/gomaasapi/+bug/1563631 zone, fieldErr := mi.maasObject.GetField("zone") if fieldErr == nil && zone != "" { return zone, nil } obj := mi.maasObject.GetMap()["zone"] if obj.IsNil() { return "", errors.New("zone property not set on maas") } zoneMap, err := obj.GetMap() if err != nil { return "", errors.New("zone property is not an expected type") } nameObj, ok := zoneMap["name"] if !ok { return "", errors.New("zone property is not set correctly: name is missing") } str, err := nameObj.GetString() if err != nil { return "", err } return str, nil }
func getEntriesFromDel(p *hbase.Delete) ([]*columnMutation, error) { errMsg := "must set at least one column for themis delete" if len(p.FamilyQuals) == 0 { return nil, errors.New(errMsg) } var ret []*columnMutation for f, _ := range p.Families { quilifiers := p.FamilyQuals[f] if len(quilifiers) == 0 { return nil, errors.New(errMsg) } for q, _ := range quilifiers { mutation := &columnMutation{ Column: &hbase.Column{ Family: []byte(f), Qual: []byte(q), }, mutationValuePair: &mutationValuePair{ typ: hbase.TypeDeleteColumn, }, } ret = append(ret, mutation) } } return ret, nil }
func (s *UndertakerSuite) TestProcessDyingModelErrorRetried(c *gc.C) { s.fix.errors = []error{ nil, // ModelInfo nil, // SetStatus nil, // WatchModelResources, errors.New("meh, will retry"), // ProcessDyingModel, errors.New("will retry again"), // ProcessDyingModel, nil, // ProcessDyingModel, nil, // SetStatus nil, // Destroy, nil, // RemoveModel } stub := s.fix.run(c, func(w worker.Worker) { workertest.CheckKilled(c, w) }) stub.CheckCallNames(c, "ModelInfo", "SetStatus", "WatchModelResources", "ProcessDyingModel", "ProcessDyingModel", "ProcessDyingModel", "SetStatus", "Destroy", "RemoveModel", ) }
func (s *testTErrorSuite) TestTError(c *C) { defer testleak.AfterTest(c)() c.Assert(ClassParser.String(), Not(Equals), "") c.Assert(ClassOptimizer.String(), Not(Equals), "") c.Assert(ClassKV.String(), Not(Equals), "") c.Assert(ClassServer.String(), Not(Equals), "") parserErr := ClassParser.New(ErrCode(1), "error 1") c.Assert(parserErr.Error(), Not(Equals), "") c.Assert(ClassParser.EqualClass(parserErr), IsTrue) c.Assert(ClassParser.NotEqualClass(parserErr), IsFalse) c.Assert(ClassOptimizer.EqualClass(parserErr), IsFalse) optimizerErr := ClassOptimizer.New(ErrCode(2), "abc") c.Assert(ClassOptimizer.EqualClass(errors.New("abc")), IsFalse) c.Assert(ClassOptimizer.EqualClass(nil), IsFalse) c.Assert(optimizerErr.Equal(optimizerErr.Gen("def")), IsTrue) c.Assert(optimizerErr.Equal(nil), IsFalse) c.Assert(optimizerErr.Equal(errors.New("abc")), IsFalse) // Test case for FastGen. c.Assert(optimizerErr.Equal(optimizerErr.FastGen("def")), IsTrue) c.Assert(optimizerErr.Equal(optimizerErr.FastGen("def: %s", "def")), IsTrue) kvErr := ClassKV.New(1062, "key already exist") e := kvErr.FastGen("Duplicate entry '%d' for key 'PRIMARY'", 1) c.Assert(e.Error(), Equals, "[kv:1062]Duplicate entry '1' for key 'PRIMARY'") kvMySQLErrCodes := map[ErrCode]uint16{ 1062: uint16(1062), } ErrClassToMySQLCodes[ClassKV] = kvMySQLErrCodes sqlErr := e.ToSQLError() c.Assert(sqlErr.Message, Equals, "Duplicate entry '1' for key 'PRIMARY'") c.Assert(sqlErr.Code, Equals, uint16(1062)) }