github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/environs/bootstrap/tools.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package bootstrap 5 6 import ( 7 "fmt" 8 "os" 9 10 "github.com/juju/errors" 11 "github.com/juju/version/v2" 12 13 "github.com/juju/juju/core/arch" 14 corebase "github.com/juju/juju/core/base" 15 "github.com/juju/juju/core/constraints" 16 coreos "github.com/juju/juju/core/os" 17 "github.com/juju/juju/core/os/ostype" 18 "github.com/juju/juju/environs" 19 envtools "github.com/juju/juju/environs/tools" 20 coretools "github.com/juju/juju/tools" 21 jujuversion "github.com/juju/juju/version" 22 ) 23 24 var ( 25 findTools = envtools.FindTools 26 ) 27 28 func localToolsArch() string { 29 toolsArch := os.Getenv("GOARCH") 30 if toolsArch == "" { 31 toolsArch = arch.HostArch() 32 } 33 return toolsArch 34 } 35 36 // validateUploadAllowed returns an error if an attempt to upload tools should 37 // not be allowed. 38 func validateUploadAllowed(env environs.ConfigGetter, toolsArch *string, toolsBase *corebase.Base, validator constraints.Validator) error { 39 // Now check that the architecture and series for which we are setting up an 40 // environment matches that from which we are bootstrapping. 41 hostArch := localToolsArch() 42 // We can't build tools for a different architecture if one is specified. 43 if toolsArch != nil && *toolsArch != hostArch { 44 return fmt.Errorf("cannot use agent built for %q using a machine running on %q", *toolsArch, hostArch) 45 } 46 hostOS := coreos.HostOS() 47 if toolsBase != nil { 48 if !ostype.OSTypeForName(toolsBase.OS).EquivalentTo(hostOS) { 49 return errors.Errorf("cannot use agent built for %q using a machine running %q", toolsBase.String(), hostOS) 50 } 51 } 52 // If no architecture is specified, ensure the target provider supports instances matching our architecture. 53 if _, err := validator.Validate(constraints.Value{Arch: &hostArch}); err != nil { 54 return errors.Errorf( 55 "model %q of type %s does not support instances running on %q", 56 env.Config().Name(), env.Config().Type(), hostArch, 57 ) 58 } 59 return nil 60 } 61 62 // findPackagedTools returns a list of tools for in simplestreams. 63 func findPackagedTools( 64 env environs.BootstrapEnviron, 65 ss envtools.SimplestreamsFetcher, 66 vers *version.Number, 67 arch *string, base *corebase.Base, 68 ) (coretools.List, error) { 69 // Look for tools in the environment's simplestreams search paths 70 // for existing tools. 71 72 // If the user hasn't asked for a specified tools version, see if 73 // one is configured in the environment. 74 if vers == nil { 75 if agentVersion, ok := env.Config().AgentVersion(); ok { 76 vers = &agentVersion 77 } 78 } 79 logger.Infof("looking for bootstrap agent binaries: version=%v", vers) 80 toolsList, findToolsErr := findBootstrapTools(env, ss, vers, arch, base) 81 logger.Infof("found %d packaged agent binaries", len(toolsList)) 82 if findToolsErr != nil { 83 return nil, findToolsErr 84 } 85 return toolsList, nil 86 } 87 88 // locallyBuildableTools returns the list of tools that 89 // can be built locally. 90 func locallyBuildableTools() (buildable coretools.List, _ version.Number, _ error) { 91 buildNumber := jujuversion.Current 92 // Increment the build number so we know it's a custom build. 93 buildNumber.Build++ 94 if !coreos.HostOS().EquivalentTo(ostype.Ubuntu) { 95 return buildable, buildNumber, nil 96 } 97 binary := version.Binary{ 98 Number: buildNumber, 99 Release: "ubuntu", 100 Arch: localToolsArch(), 101 } 102 buildable = append(buildable, &coretools.Tools{Version: binary}) 103 return buildable, buildNumber, nil 104 } 105 106 // findBootstrapTools returns a tools.List containing only those tools with 107 // which it would be reasonable to launch an environment's first machine, 108 // given the supplied constraints. If a specific agent version is not requested, 109 // all tools matching the current major.minor version are chosen. 110 func findBootstrapTools(env environs.BootstrapEnviron, ss envtools.SimplestreamsFetcher, vers *version.Number, arch *string, base *corebase.Base) (list coretools.List, err error) { 111 // Construct a tools filter. 112 cliVersion := jujuversion.Current 113 var filter coretools.Filter 114 if arch != nil { 115 filter.Arch = *arch 116 } 117 if base != nil { 118 // We can use must here, because we've already validated the base. 119 filter.OSType = base.OS 120 } 121 if vers != nil { 122 filter.Number = *vers 123 } 124 streams := envtools.PreferredStreams(vers, env.Config().Development(), env.Config().AgentStream()) 125 return findTools(ss, env, cliVersion.Major, cliVersion.Minor, streams, filter) 126 }