Пример #1
0
// DesiredVersion reports the Agent Version that we want that agent to be running
func (u *UpgraderAPI) DesiredVersion(args params.Entities) (params.VersionResults, error) {
	results := make([]params.VersionResult, len(args.Entities))
	if len(args.Entities) == 0 {
		return params.VersionResults{}, nil
	}
	agentVersion, _, err := u.getGlobalAgentVersion()
	if err != nil {
		return params.VersionResults{}, common.ServerError(err)
	}
	// Is the desired version greater than the current API server version?
	isNewerVersion := agentVersion.Compare(version.Current.Number) > 0
	for i, entity := range args.Entities {
		err := common.ErrPerm
		if u.authorizer.AuthOwner(entity.Tag) {
			if !isNewerVersion || u.entityIsManager(entity.Tag) {
				results[i].Version = &agentVersion
			} else {
				logger.Debugf("desired version is %s, but current version is %s and agent is not a manager node", agentVersion, version.Current.Number)
				results[i].Version = &version.Current.Number
			}
			err = nil
		}
		results[i].Error = common.ServerError(err)
	}
	return params.VersionResults{Results: results}, nil
}
Пример #2
0
// UpdateLatestRevisions retrieves the latest revision information from the charm store for all deployed charms
// and records this information in state.
func (api *CharmRevisionUpdaterAPI) UpdateLatestRevisions() (params.ErrorResult, error) {
	// First get the uuid for the environment to use when querying the charm store.
	env, err := api.state.Environment()
	if err != nil {
		return params.ErrorResult{Error: common.ServerError(err)}, nil
	}
	uuid := env.UUID()

	deployedCharms, err := fetchAllDeployedCharms(api.state)
	if err != nil {
		return params.ErrorResult{Error: common.ServerError(err)}, nil
	}
	// Look up the revision information for all the deployed charms.
	curls, err := retrieveLatestCharmInfo(deployedCharms, uuid)
	if err != nil {
		return params.ErrorResult{Error: common.ServerError(err)}, nil
	}
	// Add the charms and latest revision info to state as charm placeholders.
	for _, curl := range curls {
		if err = api.state.AddStoreCharmPlaceholder(curl); err != nil {
			return params.ErrorResult{Error: common.ServerError(err)}, nil
		}
	}
	return params.ErrorResult{}, nil
}
Пример #3
0
// WatchAuthorisedKeys starts a watcher to track changes to the authorised ssh keys
// for the specified machines.
// The current implementation relies on global authorised keys being stored in the environment config.
// This will change as new user management and authorisation functionality is added.
func (api *KeyUpdaterAPI) WatchAuthorisedKeys(arg params.Entities) (params.NotifyWatchResults, error) {
	results := make([]params.NotifyWatchResult, len(arg.Entities))

	canRead, err := api.getCanRead()
	if err != nil {
		return params.NotifyWatchResults{}, err
	}
	for i, entity := range arg.Entities {
		// 1. Check permissions
		if !canRead(entity.Tag) {
			results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		// 2. Check entity exists
		if _, err := api.state.FindEntity(entity.Tag); err != nil {
			if errors.IsNotFound(err) {
				results[i].Error = common.ServerError(common.ErrPerm)
			} else {
				results[i].Error = common.ServerError(err)
			}
			continue
		}
		// 3. Watch fr changes
		var err error
		watch := api.state.WatchForEnvironConfigChanges()
		// Consume the initial event.
		if _, ok := <-watch.Changes(); ok {
			results[i].NotifyWatcherId = api.resources.Register(watch)
		} else {
			err = watcher.MustErr(watch)
		}
		results[i].Error = common.ServerError(err)
	}
	return params.NotifyWatchResults{Results: results}, nil
}
Пример #4
0
func (api *UserManagerAPI) AddUser(args params.EntityPasswords) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Changes)),
	}
	if len(args.Changes) == 0 {
		return result, nil
	}
	canWrite, err := api.getCanWrite()
	if err != nil {
		result.Results[0].Error = common.ServerError(err)
		return result, err
	}
	for i, arg := range args.Changes {
		if !canWrite(arg.Tag) {
			result.Results[0].Error = common.ServerError(common.ErrPerm)
			continue
		}
		_, err := api.state.AddUser(arg.Tag, arg.Password)
		if err != nil {
			err = fmt.Errorf("Failed to create user: %v", err)
			result.Results[i].Error = common.ServerError(err)
			continue
		}
	}
	return result, nil
}
Пример #5
0
func (api *UserManagerAPI) RemoveUser(args params.Entities) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Results: make([]params.ErrorResult, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}
	canWrite, err := api.getCanWrite()
	if err != nil {
		return result, err
	}
	for i, arg := range args.Entities {
		if !canWrite(arg.Tag) {
			result.Results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		user, err := api.state.User(arg.Tag)
		if err != nil {
			result.Results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		err = user.Deactivate()
		if err != nil {
			result.Results[i].Error = common.ServerError(fmt.Errorf("Failed to remove user: %s", err))
			continue
		}
	}
	return result, nil
}
Пример #6
0
// SetRsyslogCert sets the rsyslog CACert.
func (api *RsyslogAPI) SetRsyslogCert(args params.SetRsyslogCertParams) (params.ErrorResult, error) {
	var result params.ErrorResult
	if !api.canModify {
		result.Error = common.ServerError(common.ErrBadCreds)
		return result, nil
	}
	if _, err := cert.ParseCert(string(args.CACert)); err != nil {
		result.Error = common.ServerError(err)
		return result, nil
	}
	attrs := map[string]interface{}{"rsyslog-ca-cert": string(args.CACert)}
	if err := api.st.UpdateEnvironConfig(attrs, nil, nil); err != nil {
		result.Error = common.ServerError(err)
	}
	return result, nil
}
Пример #7
0
// AuthorisedKeys reports the authorised ssh keys for the specified machines.
// The current implementation relies on global authorised keys being stored in the environment config.
// This will change as new user management and authorisation functionality is added.
func (api *KeyUpdaterAPI) AuthorisedKeys(arg params.Entities) (params.StringsResults, error) {
	if len(arg.Entities) == 0 {
		return params.StringsResults{}, nil
	}
	results := make([]params.StringsResult, len(arg.Entities))

	// For now, authorised keys are global, common to all machines.
	var keys []string
	config, configErr := api.state.EnvironConfig()
	if configErr == nil {
		keys = ssh.SplitAuthorisedKeys(config.AuthorizedKeys())
	}

	canRead, err := api.getCanRead()
	if err != nil {
		return params.StringsResults{}, err
	}
	for i, entity := range arg.Entities {
		// 1. Check permissions
		if !canRead(entity.Tag) {
			results[i].Error = common.ServerError(common.ErrPerm)
			continue
		}
		// 2. Check entity exists
		if _, err := api.state.FindEntity(entity.Tag); err != nil {
			if errors.IsNotFound(err) {
				results[i].Error = common.ServerError(common.ErrPerm)
			} else {
				results[i].Error = common.ServerError(err)
			}
			continue
		}
		// 3. Get keys
		var err error
		if configErr == nil {
			results[i].Result = keys
		} else {
			err = configErr
		}
		results[i].Error = common.ServerError(err)
	}
	return params.StringsResults{Results: results}, nil
}
Пример #8
0
func (api *API) GetEntities(args params.Entities) params.AgentGetEntitiesResults {
	results := params.AgentGetEntitiesResults{
		Entities: make([]params.AgentGetEntitiesResult, len(args.Entities)),
	}
	for i, entity := range args.Entities {
		result, err := api.getEntity(entity.Tag)
		result.Error = common.ServerError(err)
		results.Entities[i] = result
	}
	return results
}
Пример #9
0
// Tools finds the tools necessary for the given agents.
func (u *UnitUpgraderAPI) Tools(args params.Entities) (params.ToolsResults, error) {
	result := params.ToolsResults{
		Results: make([]params.ToolsResult, len(args.Entities)),
	}
	for i, entity := range args.Entities {
		result.Results[i].Error = common.ServerError(common.ErrPerm)
		if u.authorizer.AuthOwner(entity.Tag) {
			result.Results[i] = u.getMachineTools(entity.Tag)
		}
	}
	return result, nil
}
Пример #10
0
func (u *UnitUpgraderAPI) getMachineTools(tag string) params.ToolsResult {
	var result params.ToolsResult
	machine, err := u.getAssignedMachine(tag)
	if err != nil {
		result.Error = common.ServerError(err)
		return result
	}
	machineTools, err := machine.AgentTools()
	if err != nil {
		result.Error = common.ServerError(err)
		return result
	}
	// For older 1.16 upgrader workers, we need to supply a tools URL since the worker will attempt to
	// download the tools even though they already have been fetched by the machine agent. Newer upgrader
	// workers do not have this problem. So to be compatible across all versions, we return the full
	// tools metadata.
	// TODO (wallyworld) - remove in 1.20, just return machineTools
	cfg, err := u.st.EnvironConfig()
	if err != nil {
		result.Error = common.ServerError(err)
		return result
	}
	// SSLHostnameVerification defaults to true, so we need to
	// invert that, for backwards-compatibility (older versions
	// will have DisableSSLHostnameVerification: false by default).
	result.DisableSSLHostnameVerification = !cfg.SSLHostnameVerification()
	env, err := environs.New(cfg)
	if err != nil {
		result.Error = common.ServerError(err)
		return result
	}
	agentTools, err := envtools.FindExactTools(
		env, machineTools.Version.Number, machineTools.Version.Series, machineTools.Version.Arch)
	if err != nil {
		result.Error = common.ServerError(err)
		return result
	}
	result.Tools = agentTools
	return result
}
Пример #11
0
// AddMachinesV2 adds new machines with the supplied parameters.
func (c *Client) AddMachinesV2(args params.AddMachines) (params.AddMachinesResults, error) {
	results := params.AddMachinesResults{
		Machines: make([]params.AddMachinesResult, len(args.MachineParams)),
	}
	for i, p := range args.MachineParams {
		m, err := c.addOneMachine(p)
		results.Machines[i].Error = common.ServerError(err)
		if err == nil {
			results.Machines[i].Machine = m.Id()
		}
	}
	return results, nil
}
Пример #12
0
// DesiredVersion reports the Agent Version that we want that unit to be running.
// The desired version is what the unit's assigned machine is running.
func (u *UnitUpgraderAPI) DesiredVersion(args params.Entities) (params.VersionResults, error) {
	result := make([]params.VersionResult, len(args.Entities))
	if len(args.Entities) == 0 {
		return params.VersionResults{}, nil
	}
	for i, entity := range args.Entities {
		err := common.ErrPerm
		if u.authorizer.AuthOwner(entity.Tag) {
			result[i].Version, err = u.getMachineToolsVersion(entity.Tag)
		}
		result[i].Error = common.ServerError(err)
	}
	return params.VersionResults{Results: result}, nil
}
Пример #13
0
// WatchAPIVersion starts a watcher to track if there is a new version
// of the API that we want to upgrade to. The watcher tracks changes to
// the unit's assigned machine since that's where the required agent version is stored.
func (u *UnitUpgraderAPI) WatchAPIVersion(args params.Entities) (params.NotifyWatchResults, error) {
	result := params.NotifyWatchResults{
		Results: make([]params.NotifyWatchResult, len(args.Entities)),
	}
	for i, agent := range args.Entities {
		err := common.ErrPerm
		if u.authorizer.AuthOwner(agent.Tag) {
			var watcherId string
			watcherId, err = u.watchAssignedMachine(agent.Tag)
			if err == nil {
				result.Results[i].NotifyWatcherId = watcherId
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
Пример #14
0
// FindTools returns a List containing all tools matching the given parameters.
func (c *Client) FindTools(args params.FindToolsParams) (params.FindToolsResults, error) {
	result := params.FindToolsResults{}
	// Get the existing environment config from the state.
	envConfig, err := c.api.state.EnvironConfig()
	if err != nil {
		return result, err
	}
	env, err := environs.New(envConfig)
	if err != nil {
		return result, err
	}
	filter := coretools.Filter{
		Arch:   args.Arch,
		Series: args.Series,
	}
	result.List, err = envtools.FindTools(env, args.MajorVersion, args.MinorVersion, filter, envtools.DoNotAllowRetry)
	result.Error = common.ServerError(err)
	return result, nil
}
Пример #15
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 {
		err := common.ErrPerm
		if api.authorizer.AuthOwner(entity.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}
}
Пример #16
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 {
		err := common.ErrPerm
		if api.authorizer.AuthOwner(entity.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}
}
Пример #17
0
// GetRsyslogConfig returns a RsyslogConfigResult.
func (api *RsyslogAPI) GetRsyslogConfig(args params.Entities) (params.RsyslogConfigResults, error) {
	result := params.RsyslogConfigResults{
		Results: make([]params.RsyslogConfigResult, len(args.Entities)),
	}
	cfg, err := api.st.EnvironConfig()
	if err != nil {
		return result, err
	}
	for i := range args.Entities {
		rsyslogCfg, err := newRsyslogConfig(cfg, api)
		if err == nil {
			result.Results[i] = params.RsyslogConfigResult{
				CACert:    rsyslogCfg.CACert,
				Port:      rsyslogCfg.Port,
				HostPorts: rsyslogCfg.HostPorts,
			}
		} else {
			result.Results[i].Error = common.ServerError(err)
		}
	}
	return result, nil
}
Пример #18
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 {
		err := common.ErrPerm
		if u.authorizer.AuthOwner(agent.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
}
Пример #19
0
// WatchForRsyslogChanges starts a watcher to track if there are changes
// that require we update the rsyslog.d configurations for a machine and/or unit.
func (api *RsyslogAPI) WatchForRsyslogChanges(args params.Entities) (params.NotifyWatchResults, error) {
	result := params.NotifyWatchResults{
		Results: make([]params.NotifyWatchResult, len(args.Entities)),
	}
	for i := range args.Entities {
		err := common.ErrPerm
		if api.authorizer.AuthMachineAgent() || api.authorizer.AuthUnitAgent() {
			watch := api.st.WatchAPIHostPorts()
			// 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 = api.resources.Register(watch)
				err = nil
			} else {
				err = watcher.MustErr(watch)
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil

}
Пример #20
0
func serverError(err error) error {
	if err := common.ServerError(err); err != nil {
		return err
	}
	return nil
}