@@ -89,6 +89,7 @@ type CodesphereEnvironment struct {
8989 ContainerRegistryURL string `json:"-"`
9090 ExistingConfigUsed bool `json:"-"`
9191 InstallVersion string `json:"install_version"`
92+ InstallLocal string `json:"install_local"`
9293 InstallHash string `json:"install_hash"`
9394 InstallSkipSteps []string `json:"install_skip_steps"`
9495 Preemptible bool `json:"preemptible"`
@@ -160,14 +161,12 @@ func GetInfraFilePath() string {
160161}
161162
162163func (b * GCPBootstrapper ) Bootstrap () error {
163- if b .Env .InstallVersion != "" {
164- err := b .stlog .Step ("Validate input" , b .ValidateInput )
165- if err != nil {
166- return fmt .Errorf ("invalid input: %w" , err )
167- }
168-
164+ err := b .stlog .Step ("Validate input" , b .ValidateInput )
165+ if err != nil {
166+ return fmt .Errorf ("invalid input: %w" , err )
169167 }
170- err := b .stlog .Step ("Ensure install config" , b .EnsureInstallConfig )
168+
169+ err = b .stlog .Step ("Ensure install config" , b .EnsureInstallConfig )
171170 if err != nil {
172171 return fmt .Errorf ("failed to ensure install config: %w" , err )
173172 }
@@ -285,7 +284,7 @@ func (b *GCPBootstrapper) Bootstrap() error {
285284 return fmt .Errorf ("failed to generate k0s config script: %w" , err )
286285 }
287286
288- if b .Env .InstallVersion != "" {
287+ if b .Env .InstallVersion != "" || b . Env . InstallLocal != "" {
289288 err = b .stlog .Step ("Install Codesphere" , b .InstallCodesphere )
290289 if err != nil {
291290 return fmt .Errorf ("failed to install Codesphere: %w" , err )
@@ -300,7 +299,30 @@ func (b *GCPBootstrapper) Bootstrap() error {
300299 return nil
301300}
302301
302+ // ValidateInput checks that the required input parameters are set and valid
303303func (b * GCPBootstrapper ) ValidateInput () error {
304+ err := b .validateInstallVersion ()
305+ if err != nil {
306+ return err
307+ }
308+
309+ return b .validateGithubParams ()
310+ }
311+
312+ // validateInstallVersion checks if the specified install version exists and contains the required installer artifact
313+ func (b * GCPBootstrapper ) validateInstallVersion () error {
314+ if b .Env .InstallLocal != "" {
315+ if b .Env .InstallVersion != "" || b .Env .InstallHash != "" {
316+ return fmt .Errorf ("cannot specify both install-local and install-version/install-hash" )
317+ }
318+ if ! b .fw .Exists (b .Env .InstallLocal ) {
319+ return fmt .Errorf ("local installer package not found at path: %s" , b .Env .InstallLocal )
320+ }
321+ return nil
322+ }
323+ if b .Env .InstallVersion == "" {
324+ return nil
325+ }
304326 build , err := b .PortalClient .GetBuild (portal .CodesphereProduct , b .Env .InstallVersion , b .Env .InstallHash )
305327 if err != nil {
306328 return fmt .Errorf ("failed to get codesphere package: %w" , err )
@@ -323,12 +345,17 @@ func (b *GCPBootstrapper) ValidateInput() error {
323345 }
324346 }
325347
348+ return fmt .Errorf ("specified package does not contain required installer artifact %s. Existing artifacts: %s" , requiredFilename , strings .Join (filenames , ", " ))
349+ }
350+
351+ // validateGithubParams checks if the GitHub credentials are fully specified if GitHub registry is selected
352+ func (b * GCPBootstrapper ) validateGithubParams () error {
326353 ghParams := []string {b .Env .GitHubAppName , b .Env .GithubAppClientID , b .Env .GithubAppClientSecret }
327354 if slices .Contains (ghParams , "" ) && strings .Join (ghParams , "" ) != "" {
328355 return fmt .Errorf ("GitHub app credentials are not fully specified (all or none of GitHubAppName, GithubAppClientID, GithubAppClientSecret must be set)" )
329356 }
330357
331- return fmt . Errorf ( "specified package does not contain required installer artifact %s. Existing artifacts: %s" , requiredFilename , strings . Join ( filenames , ", " ))
358+ return nil
332359}
333360
334361func (b * GCPBootstrapper ) EnsureInstallConfig () error {
@@ -1401,36 +1428,70 @@ func (b *GCPBootstrapper) EnsureDNSRecords() error {
14011428}
14021429
14031430func (b * GCPBootstrapper ) InstallCodesphere () error {
1404- packageFile := "installer.tar.gz"
1405- skipSteps := b .Env .InstallSkipSteps
1431+ fullPackageFilename , err := b .ensureCodespherePackageOnJumpbox ()
1432+ if err != nil {
1433+ return fmt .Errorf ("failed to ensure Codesphere package on jumpbox: %w" , err )
1434+ }
1435+
1436+ err = b .runInstallCommand (fullPackageFilename )
1437+ if err != nil {
1438+ return fmt .Errorf ("failed to install Codesphere from jumpbox: %w" , err )
1439+ }
1440+
1441+ return nil
1442+ }
1443+
1444+ func (b * GCPBootstrapper ) ensureCodespherePackageOnJumpbox () (string , error ) {
1445+ packageFilename := "installer.tar.gz"
14061446 if b .Env .RegistryType == RegistryTypeGitHub {
1407- skipSteps = append (skipSteps , "load-container-images" )
1408- packageFile = "installer-lite.tar.gz"
1447+ packageFilename = "installer-lite.tar.gz"
14091448 }
1410- skipStepsArg := ""
1411- if len (skipSteps ) > 0 {
1412- skipStepsArg = " -s " + strings .Join (skipSteps , "," )
1449+
1450+ if b .Env .InstallLocal != "" {
1451+ b .stlog .Logf ("Copying local package %s to jumpbox..." , b .Env .InstallLocal )
1452+ fullPackageFilename := fmt .Sprintf ("local-%s" , packageFilename )
1453+ err := b .Env .Jumpbox .NodeClient .CopyFile (b .Env .Jumpbox , b .Env .InstallLocal , "/root/" + fullPackageFilename )
1454+ if err != nil {
1455+ return "" , fmt .Errorf ("failed to copy local install package to jumpbox: %w" , err )
1456+ }
1457+ return fullPackageFilename , nil
14131458 }
14141459
1415- downloadCmd := "oms-cli download package -f " + packageFile
1416- if b .Env .InstallHash != "" {
1417- downloadCmd += " -H " + b .Env .InstallHash
1460+ if b .Env .InstallVersion == "" {
1461+ return "" , errors .New ("either install version or a local package must be specified to install Codesphere" )
14181462 }
1419- downloadCmd += " " + b .Env .InstallVersion
1463+
1464+ fullPackageFilename := portal .BuildPackageFilenameFromParts (b .Env .InstallVersion , b .Env .InstallHash , packageFilename )
1465+ if b .Env .InstallHash == "" {
1466+ return "" , fmt .Errorf ("install hash must be set when install version is set" )
1467+ }
1468+ b .stlog .Logf ("Downloading Codesphere package..." )
1469+ downloadCmd := fmt .Sprintf ("oms-cli download package -f %s -H %s %s" , packageFilename , b .Env .InstallHash , b .Env .InstallVersion )
14201470 err := b .Env .Jumpbox .RunSSHCommand ("root" , downloadCmd )
14211471 if err != nil {
1422- return fmt .Errorf ("failed to download Codesphere package from jumpbox: %w" , err )
1472+ return "" , fmt .Errorf ("failed to download Codesphere package from jumpbox: %w" , err )
14231473 }
14241474
1425- fullPackageFilename := portal .BuildPackageFilenameFromParts (b .Env .InstallVersion , b .Env .InstallHash , packageFile )
1475+ return fullPackageFilename , nil
1476+ }
1477+
1478+ func (b * GCPBootstrapper ) runInstallCommand (packageFilename string ) error {
1479+ b .stlog .Logf ("Installing Codesphere..." )
14261480 installCmd := fmt .Sprintf ("oms-cli install codesphere -c /etc/codesphere/config.yaml -k %s/age_key.txt -p %s%s" ,
1427- b .Env .SecretsDir , fullPackageFilename , skipStepsArg )
1428- err = b .Env .Jumpbox .RunSSHCommand ("root" , installCmd )
1429- if err != nil {
1430- return fmt .Errorf ("failed to install Codesphere from jumpbox: %w" , err )
1481+ b .Env .SecretsDir , packageFilename , b .generateSkipStepsArg ())
1482+ return b .Env .Jumpbox .RunSSHCommand ("root" , installCmd )
1483+ }
1484+
1485+ func (b * GCPBootstrapper ) generateSkipStepsArg () string {
1486+ skipSteps := b .Env .InstallSkipSteps
1487+ if b .Env .RegistryType == RegistryTypeGitHub {
1488+ skipSteps = append (skipSteps , "load-container-images" )
1489+ }
1490+ if len (skipSteps ) == 0 {
1491+ return ""
14311492 }
14321493
1433- return nil
1494+ return " -s " + strings . Join ( skipSteps , "," )
14341495}
14351496
14361497func (b * GCPBootstrapper ) GenerateK0sConfigScript () error {
0 commit comments