Beispiel #1
0
func networkParamsToStateParams(networks []params.Network, ifaces []params.NetworkInterface) (
	[]state.NetworkInfo, []state.NetworkInterfaceInfo, error,
) {
	stateNetworks := make([]state.NetworkInfo, len(networks))
	for i, network := range networks {
		tag, err := names.ParseTag(network.Tag, names.NetworkTagKind)
		if err != nil {
			return nil, nil, err
		}
		stateNetworks[i] = state.NetworkInfo{
			Name:       tag.Id(),
			ProviderId: network.ProviderId,
			CIDR:       network.CIDR,
			VLANTag:    network.VLANTag,
		}
	}
	stateInterfaces := make([]state.NetworkInterfaceInfo, len(ifaces))
	for i, iface := range ifaces {
		tag, err := names.ParseTag(iface.NetworkTag, names.NetworkTagKind)
		if err != nil {
			return nil, nil, err
		}
		stateInterfaces[i] = state.NetworkInterfaceInfo{
			MACAddress:    iface.MACAddress,
			NetworkName:   tag.Id(),
			InterfaceName: iface.InterfaceName,
			IsVirtual:     iface.IsVirtual,
		}
	}
	return stateNetworks, stateInterfaces, nil
}
Beispiel #2
0
// cacheAPIInfo updates the local environment settings (.jenv file)
// with the provided apiInfo, assuming we've just successfully
// connected to the API server.
func cacheAPIInfo(info configstore.EnvironInfo, apiInfo *api.Info) (err error) {
	defer errors.Contextf(&err, "failed to cache API credentials")
	environUUID := ""
	if apiInfo.EnvironTag != "" {
		tag, err := names.ParseTag(apiInfo.Tag, names.EnvironTagKind)
		if err != nil {
			return err
		}
		environUUID = tag.Id()
	}
	info.SetAPIEndpoint(configstore.APIEndpoint{
		Addresses:   apiInfo.Addrs,
		CACert:      string(apiInfo.CACert),
		EnvironUUID: environUUID,
	})
	tag, err := names.ParseTag(apiInfo.Tag, names.UserTagKind)
	if err != nil {
		return err
	}
	info.SetAPICredentials(configstore.APICredentials{
		User:     tag.Id(),
		Password: apiInfo.Password,
	})
	return info.Write()
}
Beispiel #3
0
// UpdateStatus updates the status data of each given entity.
// TODO(fwereade): WTF. This method exists *only* for the convenience of the
// *client* API -- and is itself completely broken -- but we still expose it
// in every facade with a StatusSetter? FFS.
func (s *StatusSetter) UpdateStatus(args params.SetStatus) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}
	canModify, err := s.getCanModify()
	if err != nil {
		return params.ErrorResults{}, errors.Trace(err)
	}
	for i, arg := range args.Entities {
		tag, err := names.ParseTag(arg.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		err = ErrPerm
		if canModify(tag) {
			err = s.updateEntityStatusData(tag, arg.Data)
		}
		result.Results[i].Error = ServerError(err)
	}
	return result, nil
}
Beispiel #4
0
// checkCreds validates the entities credentials in the current model.
// If the entity is a user, and lookForModelUser is true, a model user must exist
// for the model.  In the case of a user logging in to the server, but
// not a model, there is no env user needed.  While we have the env
// user, if we do have it, update the last login time.
//
// Note that when logging in with lookForModelUser true, the returned
// entity will be modelUserEntity, not *state.User (external users
// don't have user entries) or *state.ModelUser (we
// don't want to lose the local user information associated with that).
func checkCreds(st *state.State, req params.LoginRequest, lookForModelUser bool, authenticator authentication.EntityAuthenticator) (state.Entity, *time.Time, error) {
	var tag names.Tag
	if req.AuthTag != "" {
		var err error
		tag, err = names.ParseTag(req.AuthTag)
		if err != nil {
			return nil, nil, errors.Trace(err)
		}
	}
	var entityFinder authentication.EntityFinder = st
	if lookForModelUser {
		// When looking up model users, use a custom
		// entity finder that looks up both the local user (if the user
		// tag is in the local domain) and the model user.
		entityFinder = modelUserEntityFinder{st}
	}
	entity, err := authenticator.Authenticate(entityFinder, tag, req)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	// For user logins, update the last login time.
	var lastLogin *time.Time
	if entity, ok := entity.(loginEntity); ok {
		userLastLogin, err := entity.LastLogin()
		if err != nil && !state.IsNeverLoggedInError(err) {
			return nil, nil, errors.Trace(err)
		}
		entity.UpdateLastLogin()
		lastLogin = &userLastLogin
	}
	return entity, lastLogin, nil
}
Beispiel #5
0
// Remove removes volumes and filesystems from state.
func (s *StorageProvisionerAPI) Remove(args params.Entities) (params.ErrorResults, error) {
	canAccess, err := s.getStorageEntityAuthFunc()
	if err != nil {
		return params.ErrorResults{}, err
	}
	results := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Entities)),
	}
	one := func(arg params.Entity) error {
		tag, err := names.ParseTag(arg.Tag)
		if err != nil {
			return errors.Trace(err)
		}
		if !canAccess(tag) {
			return common.ErrPerm
		}
		switch tag := tag.(type) {
		case names.FilesystemTag:
			return s.st.RemoveFilesystem(tag)
		case names.VolumeTag:
			return s.st.RemoveVolume(tag)
		default:
			// should have been picked up by canAccess
			logger.Debugf("unexpected %v tag", tag.Kind())
			return common.ErrPerm
		}
	}
	for i, arg := range args.Entities {
		err := one(arg)
		results.Results[i].Error = common.ServerError(err)
	}
	return results, nil
}
Beispiel #6
0
// Name returns the unit's name.
func (u *Unit) Name() string {
	tag, err := names.ParseTag(u.tag, names.UnitTagKind)
	if err != nil {
		panic(err)
	}
	return tag.Id()
}
Beispiel #7
0
func (s *machineSuite) TestEntitySetPassword(c *gc.C) {
	entity, err := apiagent.NewState(s.st).Entity(s.machine.Tag())
	c.Assert(err, jc.ErrorIsNil)

	err = entity.SetPassword("foo")
	c.Assert(err, gc.ErrorMatches, "password is only 3 bytes long, and is not a valid Agent password")
	err = entity.SetPassword("foo-12345678901234567890")
	c.Assert(err, jc.ErrorIsNil)
	err = entity.ClearReboot()
	c.Assert(err, jc.ErrorIsNil)

	err = s.machine.Refresh()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(s.machine.PasswordValid("bar"), jc.IsFalse)
	c.Assert(s.machine.PasswordValid("foo-12345678901234567890"), jc.IsTrue)

	// Check that we cannot log in to mongo with the correct password.
	// This is because there's no mongo password set for s.machine,
	// which has JobHostUnits
	info := s.MongoInfo(c)
	// TODO(dfc) this entity.Tag should return a Tag
	tag, err := names.ParseTag(entity.Tag())
	c.Assert(err, jc.ErrorIsNil)
	info.Tag = tag
	info.Password = "******"
	err = tryOpenState(s.State.ModelTag(), info)
	c.Assert(errors.Cause(err), jc.Satisfies, errors.IsUnauthorized)
}
Beispiel #8
0
// Remove removes every given entity from state, calling EnsureDead
// first, then Remove. It will fail if the entity is not present.
func (r *Remover) Remove(args params.Entities) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}
	canModify, err := r.getCanModify()
	if err != nil {
		return params.ErrorResults{}, errors.Trace(err)
	}
	for i, entity := range args.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		err = ErrPerm
		if canModify(tag) {
			err = r.removeEntity(tag)
		}
		result.Results[i].Error = ServerError(err)
	}
	return result, nil
}
Beispiel #9
0
// WatchInterfaces returns a NotifyWatcher for observing changes
// to each unit's service configuration settings.
func (n *NetworkerAPI) WatchInterfaces(args params.Entities) (params.NotifyWatchResults, error) {
	result := params.NotifyWatchResults{
		Results: make([]params.NotifyWatchResult, len(args.Entities)),
	}
	canAccess, err := n.getAuthFunc()
	if err != nil {
		return result, err
	}
	for i, entity := range args.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			result.Results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		if !canAccess(tag) {
			err = common.ErrPerm
		} else {
			tag, ok := tag.(names.MachineTag)
			if ok {
				id := tag.Id()
				result.Results[i].NotifyWatcherId, err = n.watchOneMachineInterfaces(id)
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
Beispiel #10
0
// WatchRetryStrategy watches for changes to the environment. Currently we only allow
// changes to the boolean that determines whether retries should be attempted or not.
func (h *RetryStrategyAPI) WatchRetryStrategy(args params.Entities) (params.NotifyWatchResults, error) {
	results := params.NotifyWatchResults{
		Results: make([]params.NotifyWatchResult, len(args.Entities)),
	}
	canAccess, err := h.accessUnit()
	if err != nil {
		return params.NotifyWatchResults{}, errors.Trace(err)
	}
	for i, entity := range args.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			results.Results[i].Error = common.ServerError(err)
			continue
		}
		err = common.ErrPerm
		if canAccess(tag) {
			watch := h.st.WatchForModelConfigChanges()
			// Consume the initial event. Technically, API calls to Watch
			// 'transmit' the initial event in the Watch response. But
			// NotifyWatchers have no state to transmit.
			if _, ok := <-watch.Changes(); ok {
				results.Results[i].NotifyWatcherId = h.resources.Register(watch)
				err = nil
			} else {
				err = watcher.EnsureErr(watch)
			}
		}
		results.Results[i].Error = common.ServerError(err)
	}
	return results, nil
}
Beispiel #11
0
// checkCreds validates the entities credentials in the current environment.
// If the entity is a user, and lookForEnvUser is true, an env user must exist
// for the environment.  In the case of a user logging in to the server, but
// not an environment, there is no env user needed.  While we have the env
// user, if we do have it, update the last login time.
func checkCreds(st *state.State, req params.LoginRequest, lookForEnvUser bool) (state.Entity, *time.Time, error) {
	tag, err := names.ParseTag(req.AuthTag)
	if err != nil {
		return nil, nil, err
	}
	entity, err := st.FindEntity(tag)
	if errors.IsNotFound(err) {
		// We return the same error when an entity does not exist as for a bad
		// password, so that we don't allow unauthenticated users to find
		// information about existing entities.
		logger.Debugf("entity %q not found", tag)
		return nil, nil, common.ErrBadCreds
	}
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	authenticator, err := authentication.FindEntityAuthenticator(entity)
	if err != nil {
		return nil, nil, err
	}

	if err = authenticator.Authenticate(entity, req.Credentials, req.Nonce); err != nil {
		logger.Debugf("bad credentials")
		return nil, nil, err
	}

	// For user logins, update the last login time.
	// NOTE: this code path is only for local users. When we support remote
	// user logins with bearer tokens, we will need to make sure that we also
	// update the last connection times for the environment users there.
	var lastLogin *time.Time
	if user, ok := entity.(*state.User); ok {
		userLastLogin, err := user.LastLogin()
		if err != nil && !state.IsNeverLoggedInError(err) {
			return nil, nil, errors.Trace(err)
		}
		if lookForEnvUser {
			envUser, err := st.EnvironmentUser(user.UserTag())
			if err != nil {
				return nil, nil, errors.Wrap(err, common.ErrBadCreds)
			}
			// The last connection for the environment takes precedence over
			// the local user last login time.
			userLastLogin, err = envUser.LastConnection()
			if err != nil && !state.IsNeverConnectedError(err) {
				return nil, nil, errors.Trace(err)
			}
			envUser.UpdateLastConnection()
		}
		// Only update the user's last login time if it is a successful
		// login, meaning that if we are logging into an environment, make
		// sure that there is an environment user in that environment for
		// this user.
		user.UpdateLastLogin()
		lastLogin = &userLastLogin
	}

	return entity, lastLogin, nil
}
Beispiel #12
0
// WatchLoggingConfig starts a watcher to track changes to the logging config
// for the agents specified..  Unfortunately the current infrastruture makes
// watching parts of the config non-trivial, so currently any change to the
// config will cause the watcher to notify the client.
func (api *LoggerAPI) WatchLoggingConfig(arg params.Entities) params.NotifyWatchResults {
	result := make([]params.NotifyWatchResult, len(arg.Entities))
	for i, entity := range arg.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			result[i].Error = common.ServerError(err)
			continue
		}
		err = common.ErrPerm
		if api.authorizer.AuthOwner(tag) {
			watch := api.state.WatchForEnvironConfigChanges()
			// Consume the initial event. Technically, API calls to Watch
			// 'transmit' the initial event in the Watch response. But
			// NotifyWatchers have no state to transmit.
			if _, ok := <-watch.Changes(); ok {
				result[i].NotifyWatcherId = api.resources.Register(watch)
				err = nil
			} else {
				err = watcher.MustErr(watch)
			}
		}
		result[i].Error = common.ServerError(err)
	}
	return params.NotifyWatchResults{Results: result}
}
Beispiel #13
0
// LoggingConfig reports the logging configuration for the agents specified.
func (api *LoggerAPI) LoggingConfig(arg params.Entities) params.StringResults {
	if len(arg.Entities) == 0 {
		return params.StringResults{}
	}
	results := make([]params.StringResult, len(arg.Entities))
	config, configErr := api.state.EnvironConfig()
	for i, entity := range arg.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			results[i].Error = common.ServerError(err)
			continue
		}
		err = common.ErrPerm
		if api.authorizer.AuthOwner(tag) {
			if configErr == nil {
				results[i].Result = config.LoggingConfig()
				err = nil
			} else {
				err = configErr
			}
		}
		results[i].Error = common.ServerError(err)
	}
	return params.StringResults{Results: results}
}
Beispiel #14
0
// SetPasswords sets the given password for each supplied entity, if possible.
func (pc *PasswordChanger) SetPasswords(args params.EntityPasswords) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Changes)),
	}
	if len(args.Changes) == 0 {
		return result, nil
	}
	canChange, err := pc.getCanChange()
	if err != nil {
		return params.ErrorResults{}, errors.Trace(err)
	}
	for i, param := range args.Changes {
		tag, err := names.ParseTag(param.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		if !canChange(tag) {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		if err := pc.setPassword(tag, param.Password); err != nil {
			result.Results[i].Error = ServerError(err)
		}
	}
	return result, nil
}
Beispiel #15
0
// 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
}
Beispiel #16
0
// Name returns the service name.
func (s *Service) Name() string {
	tag, err := names.ParseTag(s.tag, names.ServiceTagKind)
	if err != nil {
		panic(fmt.Sprintf("%q is not a valid service tag", s.tag))
	}
	return tag.Id()
}
Beispiel #17
0
// Actions takes a list of ActionTags, and returns the full Action for
// each ID.
func (a *ActionAPI) Actions(arg params.Entities) (params.ActionResults, error) {
	response := params.ActionResults{Results: make([]params.ActionResult, len(arg.Entities))}
	for i, entity := range arg.Entities {
		currentResult := &response.Results[i]
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		actionTag, ok := tag.(names.ActionTag)
		if !ok {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		action, err := a.state.ActionByTag(actionTag)
		if err != nil {
			currentResult.Error = common.ServerError(common.ErrBadId)
			continue
		}
		receiverTag, err := names.ActionReceiverTag(action.Receiver())
		if err != nil {
			currentResult.Error = common.ServerError(err)
			continue
		}
		response.Results[i] = common.MakeActionResult(receiverTag, action)
	}
	return response, nil
}
Beispiel #18
0
// Tools finds the tools necessary for the given agents.
func (t *ToolsGetter) Tools(args params.Entities) (params.ToolsResults, error) {
	result := params.ToolsResults{
		Results: make([]params.ToolsResult, len(args.Entities)),
	}
	canRead, err := t.getCanRead()
	if err != nil {
		return result, err
	}
	agentVersion, err := t.getGlobalAgentVersion()
	if err != nil {
		return result, err
	}
	toolsStorage, err := t.toolsStorageGetter.ToolsStorage()
	if err != nil {
		return result, err
	}
	defer toolsStorage.Close()

	for i, entity := range args.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		agentTools, err := t.oneAgentTools(canRead, tag, agentVersion, toolsStorage)
		if err == nil {
			result.Results[i].Tools = agentTools
			// TODO(axw) Get rid of this in 1.22, when all upgraders
			// are known to ignore the flag.
			result.Results[i].DisableSSLHostnameVerification = true
		}
		result.Results[i].Error = ServerError(err)
	}
	return result, nil
}
Beispiel #19
0
// CharmURL returns the charm URL for all given units or services.
func (u *UniterAPI) CharmURL(args params.Entities) (params.StringBoolResults, error) {
	result := params.StringBoolResults{
		Results: make([]params.StringBoolResult, len(args.Entities)),
	}
	accessUnitOrService := common.AuthEither(u.accessUnit, u.accessService)
	canAccess, err := accessUnitOrService()
	if err != nil {
		return params.StringBoolResults{}, err
	}
	for i, entity := range args.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			result.Results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		err = common.ErrPerm
		if canAccess(tag) {
			var unitOrService state.Entity
			unitOrService, err = u.st.FindEntity(tag)
			if err == nil {
				charmURLer := unitOrService.(interface {
					CharmURL() (*charm.URL, bool)
				})
				curl, ok := charmURLer.CharmURL()
				if curl != nil {
					result.Results[i].Result = curl.String()
					result.Results[i].Ok = ok
				}
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
Beispiel #20
0
// authenticate parses HTTP basic authentication and authorizes the
// request by looking up the provided tag and password against state.
func (h *httpHandler) authenticate(r *http.Request) error {
	parts := strings.Fields(r.Header.Get("Authorization"))
	if len(parts) != 2 || parts[0] != "Basic" {
		// Invalid header format or no header provided.
		return fmt.Errorf("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 fmt.Errorf("invalid request format")
	}
	tagPass := strings.SplitN(string(challenge), ":", 2)
	if len(tagPass) != 2 {
		return fmt.Errorf("invalid request format")
	}
	// Only allow users, not agents.
	if _, err := names.ParseTag(tagPass[0], names.UserTagKind); err != nil {
		return common.ErrBadCreds
	}
	// Ensure the credentials are correct.
	_, err = checkCreds(h.state, params.Creds{
		AuthTag:  tagPass[0],
		Password: tagPass[1],
	})
	return err
}
Beispiel #21
0
// InstanceId returns the provider specific instance id for each given
// machine or an CodeNotProvisioned error, if not set.
func (ig *InstanceIdGetter) InstanceId(args params.Entities) (params.StringResults, error) {
	result := params.StringResults{
		Results: make([]params.StringResult, len(args.Entities)),
	}
	canRead, err := ig.getCanRead()
	if err != nil {
		return result, err
	}
	for i, entity := range args.Entities {
		tag, err := names.ParseTag(entity.Tag)
		if err != nil {
			result.Results[i].Error = ServerError(ErrPerm)
			continue
		}
		err = ErrPerm
		if canRead(tag) {
			var instanceId instance.Id
			instanceId, err = ig.getInstanceId(tag)
			if err == nil {
				result.Results[i].Result = string(instanceId)
			}
		}
		result.Results[i].Error = ServerError(err)
	}
	return result, nil
}
Beispiel #22
0
// limitLoginsDuringRestore will only allow logins for restore related purposes
// while the different steps of restore are running.
func (a *MachineAgent) limitLoginsDuringRestore(req params.LoginRequest) error {
	var err error
	switch {
	case a.IsRestoreRunning():
		err = apiserver.RestoreInProgressError
	case a.IsRestorePreparing():
		err = apiserver.AboutToRestoreError
	}
	if err != nil {
		authTag, parseErr := names.ParseTag(req.AuthTag)
		if parseErr != nil {
			return errors.Annotate(err, "could not parse auth tag")
		}
		switch authTag := authTag.(type) {
		case names.UserTag:
			// use a restricted API mode
			return err
		case names.MachineTag:
			if authTag == a.Tag() {
				// allow logins from the local machine
				return nil
			}
		}
		return errors.Errorf("login for %q blocked because restore is in progress", authTag)
	}
	return nil
}
Beispiel #23
0
// Login authenticates as the entity with the given name and password.
// Subsequent requests on the state will act as that entity.  This
// method is usually called automatically by Open. The machine nonce
// should be empty unless logging in as a machine agent.
func (st *State) Login(tag, password, nonce string) error {
	var result params.LoginResult
	err := st.APICall("Admin", 0, "", "Login", &params.Creds{
		AuthTag:  tag,
		Password: password,
		Nonce:    nonce,
	}, &result)
	if err == nil {
		authtag, err := names.ParseTag(tag)
		if err != nil {
			return err
		}
		st.authTag = authtag
		hostPorts, err := addAddress(result.Servers, st.addr)
		if err != nil {
			st.Close()
			return err
		}
		st.hostPorts = hostPorts
		st.environTag = result.EnvironTag
		st.facadeVersions = make(map[string][]int, len(result.Facades))
		for _, facade := range result.Facades {
			st.facadeVersions[facade.Name] = facade.Versions
		}
	}
	return err
}
Beispiel #24
0
func (p *ProvisionerAPI) watchOneMachineContainers(arg params.WatchContainer) (params.StringsWatchResult, error) {
	nothing := params.StringsWatchResult{}
	canAccess, err := p.getAuthFunc()
	if err != nil {
		return nothing, err
	}
	if !canAccess(arg.MachineTag) {
		return nothing, common.ErrPerm
	}
	tag, err := names.ParseTag(arg.MachineTag, names.MachineTagKind)
	if err != nil {
		return nothing, err
	}
	machine, err := p.st.Machine(tag.Id())
	if err != nil {
		return nothing, err
	}
	var watch state.StringsWatcher
	if arg.ContainerType != "" {
		watch = machine.WatchContainers(instance.ContainerType(arg.ContainerType))
	} else {
		watch = machine.WatchAllContainers()
	}
	// Consume the initial event and forward it to the result.
	if changes, ok := <-watch.Changes(); ok {
		return params.StringsWatchResult{
			StringsWatcherId: p.resources.Register(watch),
			Changes:          changes,
		}, nil
	}
	return nothing, watcher.MustErr(watch)
}
Beispiel #25
0
// WatchAPIVersion starts a watcher to track if there is a new version
// of the API that we want to upgrade to
func (u *UpgraderAPI) WatchAPIVersion(args params.Entities) (params.NotifyWatchResults, error) {
	result := params.NotifyWatchResults{
		Results: make([]params.NotifyWatchResult, len(args.Entities)),
	}
	for i, agent := range args.Entities {
		tag, err := names.ParseTag(agent.Tag)
		if err != nil {
			return params.NotifyWatchResults{}, errors.Trace(err)
		}
		err = common.ErrPerm
		if u.authorizer.AuthOwner(tag) {
			watch := u.st.WatchForEnvironConfigChanges()
			// Consume the initial event. Technically, API
			// calls to Watch 'transmit' the initial event
			// in the Watch response. But NotifyWatchers
			// have no state to transmit.
			if _, ok := <-watch.Changes(); ok {
				result.Results[i].NotifyWatcherId = u.resources.Register(watch)
				err = nil
			} else {
				err = watcher.MustErr(watch)
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
Beispiel #26
0
// Id returns the machine id.
func (m *Machine) Id() string {
	tag, err := names.ParseTag(m.tag, names.MachineTagKind)
	if err != nil {
		panic(fmt.Sprintf("%q is not a valid machine tag", m.tag))
	}
	return tag.Id()
}
Beispiel #27
0
// Tag is part of the state.Block interface.
func (b *block) Tag() (names.Tag, error) {
	tag, err := names.ParseTag(b.doc.Tag)
	if err != nil {
		return nil, errors.Annotatef(err, "getting block information")
	}
	return tag, nil
}
Beispiel #28
0
// parseTag, given an entity tag, returns the collection name and id
// of the entity document.
func (st *State) parseTag(tag string) (coll string, id string, err error) {
	t, err := names.ParseTag(tag, "")
	if err != nil {
		return "", "", err
	}
	switch t.(type) {
	case names.MachineTag:
		coll = st.machines.Name
	case names.ServiceTag:
		coll = st.services.Name
	case names.UnitTag:
		coll = st.units.Name
	case names.UserTag:
		coll = st.users.Name
	case names.RelationTag:
		coll = st.relations.Name
	case names.EnvironTag:
		coll = st.environments.Name
	case names.NetworkTag:
		coll = st.networks.Name
	default:
		return "", "", fmt.Errorf("%q is not a valid collection tag", tag)
	}
	return coll, t.Id(), nil
}
Beispiel #29
0
func (s *initSystemSuite) SetUpTest(c *gc.C) {
	s.BaseSuite.SetUpTest(c)

	dataDir, err := paths.DataDir("vivid")
	c.Assert(err, jc.ErrorIsNil)
	s.dataDir = dataDir
	// Patch things out.
	s.ch = systemd.PatchNewChan(s)

	s.stub = &testing.Stub{}
	s.conn = systemd.PatchNewConn(s, s.stub)
	s.fops = systemd.PatchFileOps(s, s.stub)
	s.exec = systemd.PatchExec(s, s.stub)

	// Set up the service.
	tagStr := "machine-0"
	tag, err := names.ParseTag(tagStr)
	c.Assert(err, jc.ErrorIsNil)
	s.tag = tag
	s.name = "jujud-" + tagStr
	s.conf = common.Conf{
		Desc:      "juju agent for " + tagStr,
		ExecStart: jujud + " " + tagStr,
	}
	s.service = s.newService(c)

	// Reset any incidental calls.
	s.stub.ResetCalls()
}
Beispiel #30
0
func (u *UniterAPIV3) charmModifiedVersion(tagStr string, canAccess func(names.Tag) bool) (int, error) {
	tag, err := names.ParseTag(tagStr)
	if err != nil {
		return -1, common.ErrPerm
	}
	if !canAccess(tag) {
		return -1, common.ErrPerm
	}
	unitOrService, err := u.st.FindEntity(tag)
	if err != nil {
		return -1, err
	}
	var service *state.Service
	switch entity := unitOrService.(type) {
	case *state.Service:
		service = entity
	case *state.Unit:
		service, err = entity.Service()
		if err != nil {
			return -1, err
		}
	default:
		return -1, errors.BadRequestf("type %t does not have a CharmModifiedVersion", entity)
	}
	return service.CharmModifiedVersion(), nil
}