// FindBootstrapTools returns a ToolsList containing only those tools with // which it would be reasonable to launch an environment's first machine, // given the supplied constraints. // If the environment was not already configured to use a specific agent // version, the newest available version will be chosen and set in the // environment's configuration. func FindBootstrapTools(environ Environ, cons constraints.Value) (list tools.List, err error) { defer convertToolsError(&err) // Collect all possible compatible tools. cliVersion := version.Current.Number if list, err = FindAvailableTools(environ, cliVersion.Major); err != nil { return nil, err } // Discard all that are known to be irrelevant. cfg := environ.Config() series := cfg.DefaultSeries() log.Infof("environs: filtering tools by series: %s", series) filter := tools.Filter{Series: series} if cons.Arch != nil && *cons.Arch != "" { log.Infof("environs: filtering tools by architecture: %s", *cons.Arch) filter.Arch = *cons.Arch } if agentVersion, ok := cfg.AgentVersion(); ok { // If we already have an explicit agent version set, we're done. log.Infof("environs: filtering tools by version: %s", agentVersion) filter.Number = agentVersion return list.Match(filter) } if dev := cliVersion.IsDev() || cfg.Development(); !dev { log.Infof("environs: filtering tools by released version") filter.Released = true } if list, err = list.Match(filter); err != nil { return nil, err } // We probably still have a mix of versions available; discard older ones // and update environment configuration to use only those remaining. agentVersion, list := list.Newest() log.Infof("environs: picked newest version: %s", agentVersion) cfg, err = cfg.Apply(map[string]interface{}{ "agent-version": agentVersion.String(), }) if err == nil { err = environ.SetConfig(cfg) } if err != nil { return nil, fmt.Errorf("failed to update environment configuration: %v", err) } return list, nil }