Example #1
0
func TestPackage(t *testing.T) {
	// At this stage, Juju only supports running the apiservers and database
	// on Ubuntu. If we end up officially supporting CentOS, then we should
	// make sure we run the tests there.
	if os.HostOS() != os.Ubuntu {
		t.Skipf("skipping tests on %v", os.HostOS())
	}
	coretesting.MgoTestPackage(t)
}
Example #2
0
File: tools.go Project: bac/juju
// validateUploadAllowed returns an error if an attempt to upload tools should
// not be allowed.
func validateUploadAllowed(env environs.Environ, toolsArch, toolsSeries *string, validator constraints.Validator) error {
	// Now check that the architecture and series for which we are setting up an
	// environment matches that from which we are bootstrapping.
	hostArch := arch.HostArch()
	// We can't build tools for a different architecture if one is specified.
	if toolsArch != nil && *toolsArch != hostArch {
		return fmt.Errorf("cannot use agent built for %q using a machine running on %q", *toolsArch, hostArch)
	}
	hostOS := jujuos.HostOS()
	if toolsSeries != nil {
		toolsSeriesOS, err := series.GetOSFromSeries(*toolsSeries)
		if err != nil {
			return errors.Trace(err)
		}
		if !toolsSeriesOS.EquivalentTo(hostOS) {
			return errors.Errorf("cannot use agent built for %q using a machine running %q", *toolsSeries, hostOS)
		}
	}
	// If no architecture is specified, ensure the target provider supports instances matching our architecture.
	if _, err := validator.Validate(constraints.Value{Arch: &hostArch}); err != nil {
		return errors.Errorf(
			"model %q of type %s does not support instances running on %q",
			env.Config().Name(), env.Config().Type(), hostArch,
		)
	}
	return nil
}
Example #3
0
// NewPaths returns the set of filesystem paths that the supplied unit should
// use, given the supplied root juju data directory path.
func NewPaths(dataDir string, unitTag names.UnitTag) Paths {

	join := filepath.Join
	baseDir := join(dataDir, "agents", unitTag.String())
	stateDir := join(baseDir, "state")

	socket := func(name string, abstract bool) string {
		if os.HostOS() == os.Windows {
			return fmt.Sprintf(`\\.\pipe\%s-%s`, unitTag, name)
		}
		path := join(baseDir, name+".socket")
		if abstract {
			path = "@" + path
		}
		return path
	}

	toolsDir := tools.ToolsDir(dataDir, unitTag.String())
	return Paths{
		ToolsDir: filepath.FromSlash(toolsDir),
		Runtime: RuntimePaths{
			JujuRunSocket:     socket("run", false),
			JujucServerSocket: socket("agent", true),
		},
		State: StatePaths{
			CharmDir:        join(baseDir, "charm"),
			OperationsFile:  join(stateDir, "uniter"),
			RelationsDir:    join(stateDir, "relations"),
			BundlesDir:      join(stateDir, "bundles"),
			DeployerDir:     join(stateDir, "deployer"),
			StorageDir:      join(stateDir, "storage"),
			MetricsSpoolDir: join(stateDir, "spool", "metrics"),
		},
	}
}
Example #4
0
// NewWorker returns a worker that keeps track of
// the machine's authorised ssh keys and ensures the
// ~/.ssh/authorized_keys file is up to date.
func NewWorker(st *keyupdater.State, agentConfig agent.Config) worker.Worker {
	if os.HostOS() == os.Windows {
		return worker.NewNoOpWorker()
	}
	kw := &keyupdaterWorker{st: st, tag: agentConfig.Tag().(names.MachineTag)}
	return worker.NewNotifyWorker(kw)
}
Example #5
0
func (runner *runner) runCharmHookWithLocation(hookName, charmLocation string) error {
	srv, err := runner.startJujucServer()
	if err != nil {
		return err
	}
	defer srv.Close()

	env, err := runner.context.HookVars(runner.paths)
	if err != nil {
		return errors.Trace(err)
	}
	if jujuos.HostOS() == jujuos.Windows {
		// TODO(fwereade): somehow consolidate with utils/exec?
		// We don't do this on the other code path, which uses exec.RunCommands,
		// because that already has handling for windows environment requirements.
		env = mergeWindowsEnvironment(env, os.Environ())
	}

	debugctx := debug.NewHooksContext(runner.context.UnitName())
	if session, _ := debugctx.FindSession(); session != nil && session.MatchHook(hookName) {
		logger.Infof("executing %s via debug-hooks", hookName)
		err = session.RunHook(hookName, runner.paths.GetCharmDir(), env)
	} else {
		err = runner.runCharmHook(hookName, env, charmLocation)
	}
	return runner.context.Flush(hookName, err)
}
Example #6
0
func syslogUserGroup() (string, string) {
	switch os.HostOS() {
	case os.CentOS:
		return "root", "adm"
	default:
		return "syslog", "syslog"
	}
}
Example #7
0
func syslogUser() string {
	switch jujuos.HostOS() {
	case jujuos.CentOS:
		return "root"
	default:
		return "syslog"
	}
}
Example #8
0
File: run.go Project: imoapps/juju
// appendProxyToCommands activates proxy settings on platforms
// that support this feature via the command line. Currently this
// will work on most GNU/Linux systems, but has no use in Windows
// where the proxy settings are taken from the registry or from
// application specific settings (proxy settings in firefox ignore
// registry values on Windows).
func (c *RunCommand) appendProxyToCommands() string {
	switch jujuos.HostOS() {
	case jujuos.Ubuntu:
		return `[ -f "/home/ubuntu/.juju-proxy" ] && . "/home/ubuntu/.juju-proxy"` + "\n" + c.commands
	default:
		return c.commands
	}
}
Example #9
0
func (w *proxyWorker) writeEnvironment() error {
	switch os.HostOS() {
	case os.Windows:
		return w.writeEnvironmentToRegistry()
	default:
		return w.writeEnvironmentFile()
	}
}
Example #10
0
// OSDependentEnvVars returns the OS-dependent environment variables that
// should be set for a hook context.
func OSDependentEnvVars(paths Paths) []string {
	switch jujuos.HostOS() {
	case jujuos.Windows:
		return windowsEnv(paths)
	case jujuos.Ubuntu:
		return ubuntuEnv(paths)
	case jujuos.CentOS:
		return centosEnv(paths)
	}
	return nil
}
Example #11
0
// removeJujudpass removes a file that is no longer used on versions >1.25
// The Jujud.pass file was created during cloud init before
// so we know it's location for sure in case it exists
func removeJujudpass(context Context) error {
	if os.HostOS() == os.Windows {
		fileLocation := "C:\\Juju\\Jujud.pass"
		if err := osRemove(fileLocation); err != nil {
			// Don't fail the step if we can't get rid of the old files.
			// We don't actually care if they still exist or not.
			logger.Warningf("can't delete old password file %q: %s", fileLocation, err)
		}
	}
	return nil
}
Example #12
0
// newRsyslogConfigWorker returns a worker.Worker that uses
// WatchForRsyslogChanges and updates rsyslog configuration based
// on changes. The worker will remove the configuration file
// on teardown.
func newRsyslogConfigWorker(st *apirsyslog.State, mode RsyslogMode, tag names.Tag, namespace string, stateServerAddrs []string, jujuConfigDir string) (worker.Worker, error) {
	if jujuos.HostOS() == jujuos.Windows && mode == RsyslogModeAccumulate {
		return worker.NewNoOpWorker(), nil
	}
	handler, err := newRsyslogConfigHandler(st, mode, tag, namespace, stateServerAddrs, jujuConfigDir)
	if err != nil {
		return nil, err
	}
	logger.Debugf("starting rsyslog worker mode %v for %q %q", mode, tag, namespace)
	return worker.NewNotifyWorker(handler), nil
}
Example #13
0
func (s *supportedSeriesSuite) TestSeriesVersion(c *gc.C) {
	// There is no distro-info on Windows or CentOS.
	if os.HostOS() != os.Ubuntu {
		c.Skip("This test is only relevant on Ubuntu.")
	}
	vers, err := series.SeriesVersion("precise")
	if err != nil && err.Error() == `invalid series "precise"` {
		c.Fatalf(`Unable to lookup series "precise", you may need to: apt-get install distro-info`)
	}
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(vers, gc.Equals, "12.04")
}
Example #14
0
// addJujuRegKey tries to create the same key that is now created during cloudinit
// on machines having version 1.25 or up
// Since support for ACL's in golang is quite disastrous at the moment, and they're
// not especially easy to use, this is done using the exact same steps used in cloudinit
func addJujuRegKey(context Context) error {
	if os.HostOS() == os.Windows {
		cmds := cloudconfig.CreateJujuRegistryKeyCmds()
		_, err := execRunCommands(exec.RunParams{
			Commands: strings.Join(cmds, "\n"),
		})
		if err != nil {
			return errors.Annotate(err, "could not create juju registry key")
		}
		logger.Infof("created juju registry key at %s", osenv.JujuRegistryKey)
		return nil
	}
	return nil
}
Example #15
0
// locallyBuildableTools returns the list of tools that
// can be built locally, for series of the same OS.
func locallyBuildableTools() (buildable coretools.List) {
	for _, ser := range series.SupportedSeries() {
		if os, err := series.GetOSFromSeries(ser); err != nil || os != jujuos.HostOS() {
			continue
		}
		binary := version.Binary{
			Number: version.Current.Number,
			Series: ser,
			Arch:   arch.HostArch(),
		}
		// Increment the build number so we know it's a development build.
		binary.Build++
		buildable = append(buildable, &coretools.Tools{Version: binary})
	}
	return buildable
}
Example #16
0
func GetPackageManager() (s PackageManagerStruct, err error) {
	switch jujuos.HostOS() {
	case jujuos.CentOS:
		s.PackageManager = "yum"
		s.PackageQuery = "yum"
		s.RepositoryManager = "yum-config-manager --add-repo"
	case jujuos.Ubuntu:
		s.PackageManager = "apt-get"
		s.PackageQuery = "dpkg-query"
		s.RepositoryManager = "add-apt-repository"
	default:
		s.PackageManager = "apt-get"
		s.PackageQuery = "dpkg-query"
		s.RepositoryManager = "add-apt-repository"
	}
	return s, nil
}
Example #17
0
// hookCommand constructs an appropriate command to be passed to
// exec.Command(). The exec package uses cmd.exe as default on windows.
// cmd.exe does not know how to execute ps1 files by default, and
// powershell needs a few flags to allow execution (-ExecutionPolicy)
// and propagate error levels (-File). .cmd and .bat files can be run
// directly.
func hookCommand(hook string) []string {
	if jujuos.HostOS() != jujuos.Windows {
		// we are not running on windows,
		// just return the hook name
		return []string{hook}
	}
	if strings.HasSuffix(hook, ".ps1") {
		return []string{
			"powershell.exe",
			"-NonInteractive",
			"-ExecutionPolicy",
			"RemoteSigned",
			"-File",
			hook,
		}
	}
	return []string{hook}
}
Example #18
0
func (s *RunTestSuite) runListenerForAgent(c *gc.C, agent string) {
	agentDir := filepath.Join(cmdutil.DataDir, "agents", agent)
	err := os.MkdirAll(agentDir, 0755)
	c.Assert(err, jc.ErrorIsNil)
	var socketPath string
	switch jujuos.HostOS() {
	case jujuos.Windows:
		socketPath = fmt.Sprintf(`\\.\pipe\%s-run`, agent)
	default:
		socketPath = fmt.Sprintf("%s/run.socket", agentDir)
	}
	listener, err := uniter.NewRunListener(&mockRunner{c}, socketPath)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(listener, gc.NotNil)
	s.AddCleanup(func(*gc.C) {
		c.Assert(listener.Close(), jc.ErrorIsNil)
	})
}
Example #19
0
// NewWorker returns a worker that keeps track of
// the machine's authorised ssh keys and ensures the
// ~/.ssh/authorized_keys file is up to date.
func NewWorker(st *keyupdater.State, agentConfig agent.Config) (worker.Worker, error) {
	machineTag, ok := agentConfig.Tag().(names.MachineTag)
	if !ok {
		return nil, errors.NotValidf("machine tag %v", agentConfig.Tag())
	}
	if os.HostOS() == os.Windows {
		return worker.NewNoOpWorker(), nil
	}
	w, err := watcher.NewNotifyWorker(watcher.NotifyConfig{
		Handler: &keyupdaterWorker{
			st:  st,
			tag: machineTag,
		},
	})
	if err != nil {
		return nil, errors.Trace(err)
	}
	return w, nil
}
Example #20
0
File: tools.go Project: bac/juju
// locallyBuildableTools returns the list of tools that
// can be built locally, for series of the same OS.
func locallyBuildableTools(toolsSeries *string) (buildable coretools.List, _ version.Number) {
	buildNumber := jujuversion.Current
	// Increment the build number so we know it's a custom build.
	buildNumber.Build++
	for _, ser := range series.SupportedSeries() {
		if os, err := series.GetOSFromSeries(ser); err != nil || !os.EquivalentTo(jujuos.HostOS()) {
			continue
		}
		if toolsSeries != nil && ser != *toolsSeries {
			continue
		}
		binary := version.Binary{
			Number: buildNumber,
			Series: ser,
			Arch:   arch.HostArch(),
		}
		buildable = append(buildable, &coretools.Tools{Version: binary})
	}
	return buildable, buildNumber
}
Example #21
0
// searchHook will search, in order, hooks suffixed with extensions
// in windowsSuffixOrder. As windows cares about extensions to determine
// how to execute a file, we will allow several suffixes, with powershell
// being default.
func searchHook(charmDir, hook string) (string, error) {
	hookFile := filepath.Join(charmDir, hook)
	if jujuos.HostOS() != jujuos.Windows {
		// we are not running on windows,
		// there is no need to look for suffixed hooks
		return lookPath(hookFile)
	}
	for _, suffix := range windowsSuffixOrder {
		file := fmt.Sprintf("%s%s", hookFile, suffix)
		foundHook, err := lookPath(file)
		if err != nil {
			if context.IsMissingHookError(err) {
				// look for next suffix
				continue
			}
			return "", err
		}
		return foundHook, nil
	}
	return "", context.NewMissingHookError(hook)
}
Example #22
0
func (s *discoverySuite) TestDiscoverServiceLocalHost(c *gc.C) {
	var localInitSystem string
	var err error
	switch runtime.GOOS {
	case "windows":
		localInitSystem = service.InitSystemWindows
	case "linux":
		localInitSystem, err = service.VersionInitSystem(series.HostSeries())
	}
	c.Assert(err, gc.IsNil)

	test := discoveryTest{
		os:       jujuos.HostOS(),
		series:   series.HostSeries(),
		expected: localInitSystem,
	}
	test.disableVersionDiscovery(s)

	svc, err := service.DiscoverService(s.name, s.conf)
	c.Assert(err, jc.ErrorIsNil)

	test.checkService(c, svc, err, s.name, s.conf)
}
Example #23
0
// validateUploadAllowed returns an error if an attempt to upload tools should
// not be allowed.
func validateUploadAllowed(env environs.Environ, toolsArch, toolsSeries *string) error {
	// Now check that the architecture and series for which we are setting up an
	// environment matches that from which we are bootstrapping.
	hostArch := arch.HostArch()
	// We can't build tools for a different architecture if one is specified.
	if toolsArch != nil && *toolsArch != hostArch {
		return fmt.Errorf("cannot build tools for %q using a machine running on %q", *toolsArch, hostArch)
	}
	hostOS := jujuos.HostOS()
	if toolsSeries != nil {
		toolsSeriesOS, err := series.GetOSFromSeries(*toolsSeries)
		if err != nil {
			return errors.Trace(err)
		}
		if toolsSeriesOS != hostOS {
			return errors.Errorf("cannot build tools for %q using a machine running %q", *toolsSeries, hostOS)
		}
	}
	// If no architecture is specified, ensure the target provider supports instances matching our architecture.
	supportedArchitectures, err := env.SupportedArchitectures()
	if err != nil {
		return fmt.Errorf(
			"no packaged tools available and cannot determine model's supported architectures: %v", err)
	}
	archSupported := false
	for _, arch := range supportedArchitectures {
		if hostArch == arch {
			archSupported = true
			break
		}
	}
	if !archSupported {
		envType := env.Config().Type()
		return errors.Errorf("model %q of type %s does not support instances running on %q", env.Config().Name(), envType, hostArch)
	}
	return nil
}
Example #24
0
func socketName(baseDir, unitTag string) string {
	if os.HostOS() == os.Windows {
		return fmt.Sprintf(`\\.\pipe\collect-metrics-%s`, unitTag)
	}
	return path.Join(baseDir, defaultSocketName)
}
Example #25
0
	reader, err := s.factory.Reader()
	if err != nil {
		return errors.Trace(err)
	}
	defer reader.Close()
	return s.sendMetrics(reader)
}

func (s *sender) stop() {
	if s.listener != nil {
		s.listener.Stop()
	}
}

var socketName = func(baseDir, unitTag string) string {
	if os.HostOS() == os.Windows {
		return fmt.Sprintf(`\\.\pipe\send-metrics-%s`, unitTag)
	}
	return path.Join(baseDir, defaultSocketName)
}

func newSender(client metricsadder.MetricsAdderClient, factory spool.MetricFactory, baseDir, unitTag string) (*sender, error) {
	s := &sender{
		client:  client,
		factory: factory,
	}
	listener, err := spool.NewSocketListener(socketName(baseDir, unitTag), s)
	if err != nil {
		return nil, errors.Trace(err)
	}
	s.listener = listener
Example #26
0
func (u *Uniter) init(unitTag names.UnitTag) (err error) {
	u.unit, err = u.st.Unit(unitTag)
	if err != nil {
		return err
	}
	if u.unit.Life() == params.Dead {
		// If we started up already dead, we should not progress further. If we
		// become Dead immediately after starting up, we may well complete any
		// operations in progress before detecting it; but that race is fundamental
		// and inescapable, whereas this one is not.
		return worker.ErrTerminateAgent
	}
	if err = u.setupLocks(); err != nil {
		return err
	}
	if err := jujuc.EnsureSymlinks(u.paths.ToolsDir); err != nil {
		return err
	}
	if err := os.MkdirAll(u.paths.State.RelationsDir, 0755); err != nil {
		return errors.Trace(err)
	}
	relations, err := relation.NewRelations(
		u.st, unitTag, u.paths.State.CharmDir,
		u.paths.State.RelationsDir, u.catacomb.Dying(),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create relations")
	}
	u.relations = relations
	storageAttachments, err := storage.NewAttachments(
		u.st, unitTag, u.paths.State.StorageDir, u.catacomb.Dying(),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create storage hook source")
	}
	u.storage = storageAttachments
	u.commands = runcommands.NewCommands()
	u.commandChannel = make(chan string)

	deployer, err := charm.NewDeployer(
		u.paths.State.CharmDir,
		u.paths.State.DeployerDir,
		charm.NewBundlesDir(u.paths.State.BundlesDir, u.downloader),
	)
	if err != nil {
		return errors.Annotatef(err, "cannot create deployer")
	}
	u.deployer = &deployerProxy{deployer}
	contextFactory, err := context.NewContextFactory(
		u.st, unitTag, u.leadershipTracker, u.relations.GetInfo, u.storage, u.paths, u.clock,
	)
	if err != nil {
		return err
	}
	runnerFactory, err := runner.NewFactory(
		u.st, u.paths, contextFactory,
	)
	if err != nil {
		return errors.Trace(err)
	}
	u.operationFactory = operation.NewFactory(operation.FactoryParams{
		Deployer:       u.deployer,
		RunnerFactory:  runnerFactory,
		Callbacks:      &operationCallbacks{u},
		Abort:          u.catacomb.Dying(),
		MetricSpoolDir: u.paths.GetMetricsSpoolDir(),
	})

	operationExecutor, err := u.newOperationExecutor(u.paths.State.OperationsFile, u.getServiceCharmURL, u.acquireExecutionLock)
	if err != nil {
		return errors.Trace(err)
	}
	u.operationExecutor = operationExecutor

	logger.Debugf("starting juju-run listener on unix:%s", u.paths.Runtime.JujuRunSocket)
	commandRunner, err := NewChannelCommandRunner(ChannelCommandRunnerConfig{
		Abort:          u.catacomb.Dying(),
		Commands:       u.commands,
		CommandChannel: u.commandChannel,
	})
	if err != nil {
		return errors.Annotate(err, "creating command runner")
	}
	u.runListener, err = NewRunListener(RunListenerConfig{
		SocketPath:    u.paths.Runtime.JujuRunSocket,
		CommandRunner: commandRunner,
	})
	if err != nil {
		return errors.Trace(err)
	}
	rlw := newRunListenerWrapper(u.runListener)
	if err := u.catacomb.Add(rlw); err != nil {
		return errors.Trace(err)
	}
	// The socket needs to have permissions 777 in order for other users to use it.
	if jujuos.HostOS() != jujuos.Windows {
		return os.Chmod(u.paths.Runtime.JujuRunSocket, 0777)
	}
	return nil
}
Example #27
0
// PrepareForBootstrap implements environs.EnvironProvider.PrepareForBootstrap.
func (p environProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
	attrs := map[string]interface{}{
		// We must not proxy SSH through the API server in a
		// local provider environment. Besides not being useful,
		// it may not work; there is no requirement for sshd to
		// be available on machine-0.
		"proxy-ssh": false,
	}
	if _, ok := cfg.AgentVersion(); !ok {
		attrs["agent-version"] = version.Current.String()
	}
	if namespace, _ := cfg.UnknownAttrs()["namespace"].(string); namespace == "" {
		username := os.Getenv("USER")
		if username == "" {
			u, err := userCurrent()
			if err != nil {
				return nil, errors.Annotate(err, "failed to determine username for namespace")
			}
			username = u.Username
		}
		attrs["namespace"] = fmt.Sprintf("%s-%s", username, cfg.Name())
	}

	setIfNotBlank := func(key, value string) {
		if value != "" {
			attrs[key] = value
		}
	}
	// If the user has specified no values for any of the four normal
	// proxies, then look in the environment and set them.
	logger.Tracef("Look for proxies?")
	if cfg.HttpProxy() == "" &&
		cfg.HttpsProxy() == "" &&
		cfg.FtpProxy() == "" &&
		cfg.NoProxy() == "" {
		proxySettings := proxy.DetectProxies()
		logger.Tracef("Proxies detected %#v", proxySettings)
		setIfNotBlank(config.HttpProxyKey, proxySettings.Http)
		setIfNotBlank(config.HttpsProxyKey, proxySettings.Https)
		setIfNotBlank(config.FtpProxyKey, proxySettings.Ftp)
		setIfNotBlank(config.NoProxyKey, proxySettings.NoProxy)
	}
	if jujuos.HostOS() == jujuos.Ubuntu {
		if cfg.AptHttpProxy() == "" &&
			cfg.AptHttpsProxy() == "" &&
			cfg.AptFtpProxy() == "" {
			proxySettings, err := detectPackageProxies()
			if err != nil {
				return nil, errors.Trace(err)
			}
			setIfNotBlank(config.AptHttpProxyKey, proxySettings.Http)
			setIfNotBlank(config.AptHttpsProxyKey, proxySettings.Https)
			setIfNotBlank(config.AptFtpProxyKey, proxySettings.Ftp)
		}
	}

	cfg, err := cfg.Apply(attrs)
	if err != nil {
		return nil, errors.Trace(err)
	}
	// Make sure everything is valid.
	cfg, err = p.Validate(cfg, nil)
	if err != nil {
		return nil, errors.Trace(err)
	}

	// The user must not set bootstrap-ip; this is determined by the provider,
	// and its presence used to determine whether the environment has yet been
	// bootstrapped.
	if _, ok := cfg.UnknownAttrs()["bootstrap-ip"]; ok {
		return nil, errors.Errorf("bootstrap-ip must not be specified")
	}
	err = checkLocalPort(cfg.StatePort(), "state port")
	if err != nil {
		return nil, errors.Trace(err)
	}
	err = checkLocalPort(cfg.APIPort(), "API port")
	if err != nil {
		return nil, errors.Trace(err)
	}

	return p.Open(cfg)
}
Example #28
0
func (p *collectPaths) GetJujucSocket() string {
	if os.HostOS() == os.Windows {
		return fmt.Sprintf(`\\.\pipe\%s-metrics`, p.unitTag)
	}
	return filepath.Join(p.baseDir(), "metrics.socket@")
}
Example #29
0
func (s *prepareSuite) TestPrepareCapturesEnvironment(c *gc.C) {
	baseConfig, err := config.New(config.UseDefaults, map[string]interface{}{
		"type": provider.Local,
		"name": "test",
	})
	c.Assert(err, jc.ErrorIsNil)
	provider, err := environs.Provider(provider.Local)
	c.Assert(err, jc.ErrorIsNil)

	for i, test := range []struct {
		message          string
		extraConfig      map[string]interface{}
		env              map[string]string
		aptOutput        string
		expectedProxy    proxy.Settings
		expectedAptProxy proxy.Settings
	}{{
		message: "nothing set",
	}, {
		message: "grabs proxy from environment",
		env: map[string]string{
			"http_proxy":  "http://[email protected]",
			"HTTPS_PROXY": "https://[email protected]",
			"ftp_proxy":   "ftp://[email protected]",
			"no_proxy":    "localhost,10.0.3.1",
		},
		expectedProxy: proxy.Settings{
			Http:    "http://[email protected]",
			Https:   "https://[email protected]",
			Ftp:     "ftp://[email protected]",
			NoProxy: "localhost,10.0.3.1",
		},
		expectedAptProxy: proxy.Settings{
			Http:  "http://[email protected]",
			Https: "https://[email protected]",
			Ftp:   "ftp://[email protected]",
		},
	}, {
		message: "skips proxy from environment if http-proxy set",
		extraConfig: map[string]interface{}{
			"http-proxy": "http://[email protected]",
		},
		env: map[string]string{
			"http_proxy":  "http://[email protected]",
			"HTTPS_PROXY": "https://[email protected]",
			"ftp_proxy":   "ftp://[email protected]",
		},
		expectedProxy: proxy.Settings{
			Http: "http://[email protected]",
		},
		expectedAptProxy: proxy.Settings{
			Http: "http://[email protected]",
		},
	}, {
		message: "skips proxy from environment if https-proxy set",
		extraConfig: map[string]interface{}{
			"https-proxy": "https://[email protected]",
		},
		env: map[string]string{
			"http_proxy":  "http://[email protected]",
			"HTTPS_PROXY": "https://[email protected]",
			"ftp_proxy":   "ftp://[email protected]",
		},
		expectedProxy: proxy.Settings{
			Https: "https://[email protected]",
		},
		expectedAptProxy: proxy.Settings{
			Https: "https://[email protected]",
		},
	}, {
		message: "skips proxy from environment if ftp-proxy set",
		extraConfig: map[string]interface{}{
			"ftp-proxy": "ftp://[email protected]",
		},
		env: map[string]string{
			"http_proxy":  "http://[email protected]",
			"HTTPS_PROXY": "https://[email protected]",
			"ftp_proxy":   "ftp://[email protected]",
		},
		expectedProxy: proxy.Settings{
			Ftp: "ftp://[email protected]",
		},
		expectedAptProxy: proxy.Settings{
			Ftp: "ftp://[email protected]",
		},
	}, {
		message: "skips proxy from environment if no-proxy set",
		extraConfig: map[string]interface{}{
			"no-proxy": "localhost,10.0.3.1",
		},
		env: map[string]string{
			"http_proxy":  "http://[email protected]",
			"HTTPS_PROXY": "https://[email protected]",
			"ftp_proxy":   "ftp://[email protected]",
		},
		expectedProxy: proxy.Settings{
			NoProxy: "localhost,10.0.3.1",
		},
	}, {
		message: "apt-proxies detected",
		aptOutput: `CommandLine::AsString "apt-config dump";
Acquire::http::Proxy  "10.0.3.1:3142";
Acquire::https::Proxy "";
Acquire::ftp::Proxy "";
Acquire::magic::Proxy "";
`,
		expectedAptProxy: proxy.Settings{
			Http:  "http://10.0.3.1:3142",
			Https: "",
			Ftp:   "",
		},
	}, {
		message: "apt-proxies not used if apt-http-proxy set",
		extraConfig: map[string]interface{}{
			"apt-http-proxy": "http://value-set",
		},
		aptOutput: `CommandLine::AsString "apt-config dump";
Acquire::http::Proxy  "10.0.3.1:3142";
Acquire::https::Proxy "";
Acquire::ftp::Proxy "";
Acquire::magic::Proxy "";
`,
		expectedAptProxy: proxy.Settings{
			Http: "http://value-set",
		},
	}, {
		message: "apt-proxies not used if apt-https-proxy set",
		extraConfig: map[string]interface{}{
			"apt-https-proxy": "https://value-set",
		},
		aptOutput: `CommandLine::AsString "apt-config dump";
Acquire::http::Proxy  "10.0.3.1:3142";
Acquire::https::Proxy "";
Acquire::ftp::Proxy "";
Acquire::magic::Proxy "";
`,
		expectedAptProxy: proxy.Settings{
			Https: "https://value-set",
		},
	}, {
		message: "apt-proxies not used if apt-ftp-proxy set",
		extraConfig: map[string]interface{}{
			"apt-ftp-proxy": "ftp://value-set",
		},
		aptOutput: `CommandLine::AsString "apt-config dump";
Acquire::http::Proxy  "10.0.3.1:3142";
Acquire::https::Proxy "";
Acquire::ftp::Proxy "";
Acquire::magic::Proxy "";
`,
		expectedAptProxy: proxy.Settings{
			Ftp: "ftp://value-set",
		},
	}} {
		c.Logf("\n%v: %s", i, test.message)
		cleanup := []func(){}
		for key, value := range test.env {
			restore := testing.PatchEnvironment(key, value)
			cleanup = append(cleanup, restore)
		}
		_, restore := testing.HookCommandOutput(&manager.CommandOutput, []byte(test.aptOutput), nil)
		cleanup = append(cleanup, restore)
		testConfig := baseConfig
		if test.extraConfig != nil {
			testConfig, err = baseConfig.Apply(test.extraConfig)
			c.Assert(err, jc.ErrorIsNil)
		}
		env, err := provider.PrepareForBootstrap(envtesting.BootstrapContext(c), testConfig)
		c.Assert(err, jc.ErrorIsNil)

		envConfig := env.Config()
		c.Assert(envConfig.HttpProxy(), gc.Equals, test.expectedProxy.Http)
		c.Assert(envConfig.HttpsProxy(), gc.Equals, test.expectedProxy.Https)
		c.Assert(envConfig.FtpProxy(), gc.Equals, test.expectedProxy.Ftp)
		c.Assert(envConfig.NoProxy(), gc.Equals, test.expectedProxy.NoProxy)

		if jujuos.HostOS() == jujuos.Ubuntu {
			c.Assert(envConfig.AptHttpProxy(), gc.Equals, test.expectedAptProxy.Http)
			c.Assert(envConfig.AptHttpsProxy(), gc.Equals, test.expectedAptProxy.Https)
			c.Assert(envConfig.AptFtpProxy(), gc.Equals, test.expectedAptProxy.Ftp)
		}
		for _, clean := range cleanup {
			clean()
		}
	}
}
Example #30
0
func (cs *ConnectSuite) SetUpSuite(c *gc.C) {
	cs.IsolationSuite.SetUpSuite(c)
	if jujuos.HostOS() != jujuos.Ubuntu {
		c.Skip("lxd is only supported on Ubuntu at the moment")
	}
}