diff --git a/cmd/init_ethereum.go b/cmd/init_ethereum.go index 14d29e40..3ec1b72f 100644 --- a/cmd/init_ethereum.go +++ b/cmd/init_ethereum.go @@ -1,4 +1,4 @@ -// Copyright © 2021 Kaleido, Inc. +// Copyright © 2023 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // @@ -37,7 +37,6 @@ var initEthereumCmd = &cobra.Command{ RunE: func(cmd *cobra.Command, args []string) error { ctx := log.WithVerbosity(context.Background(), verbose) ctx = log.WithLogger(ctx, logger) - var stackName string stackManager := stacks.NewStackManager(ctx) if err := initCommon(args); err != nil { return err @@ -46,7 +45,7 @@ var initEthereumCmd = &cobra.Command{ stackManager.RemoveStack() return err } - fmt.Printf("Stack '%s' created!\nTo start your new stack run:\n\n%s start %s\n", stackName, rootCmd.Use, stackName) + fmt.Printf("Stack '%s' created!\nTo start your new stack run:\n\n%s start %s\n", initOptions.StackName, rootCmd.Use, initOptions.StackName) fmt.Printf("\nYour docker compose file for this stack can be found at: %s\n\n", filepath.Join(stackManager.Stack.StackDir, "docker-compose.yml")) return nil }, diff --git a/cmd/init_fabric.go b/cmd/init_fabric.go index 220ac408..ffc158d5 100644 --- a/cmd/init_fabric.go +++ b/cmd/init_fabric.go @@ -1,4 +1,4 @@ -// Copyright © 2021 Kaleido, Inc. +// Copyright © 2023 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/cmd/pull.go b/cmd/pull.go index de733225..f431e74e 100644 --- a/cmd/pull.go +++ b/cmd/pull.go @@ -1,4 +1,4 @@ -// Copyright © 2021 Kaleido, Inc. +// Copyright © 2023 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // @@ -22,6 +22,7 @@ import ( "time" "github.com/briandowns/spinner" + "github.com/hyperledger/firefly-cli/internal/docker" "github.com/hyperledger/firefly-cli/internal/log" "github.com/hyperledger/firefly-cli/internal/stacks" "github.com/hyperledger/firefly-cli/pkg/types" @@ -41,12 +42,17 @@ Pull the images for a stack . var spin *spinner.Spinner if fancyFeatures && !verbose { spin = spinner.New(spinner.CharSets[11], 100*time.Millisecond) - spin.FinalMSG = "done" logger = log.NewSpinnerLogger(spin) } ctx := log.WithVerbosity(context.Background(), verbose) ctx = log.WithLogger(ctx, logger) + version, err := docker.CheckDockerConfig() + if err != nil { + return err + } + ctx = context.WithValue(ctx, docker.CtxComposeVersionKey{}, version) + stackManager := stacks.NewStackManager(ctx) if len(args) == 0 { return errors.New("no stack specified") diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 2b79a31d..1a960201 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -1,4 +1,4 @@ -// Copyright © 2021 Kaleido, Inc. +// Copyright © 2023 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // @@ -19,36 +19,56 @@ package cmd import ( "context" "fmt" + "time" + "github.com/briandowns/spinner" + "github.com/hyperledger/firefly-cli/internal/docker" "github.com/hyperledger/firefly-cli/internal/log" "github.com/hyperledger/firefly-cli/internal/stacks" "github.com/spf13/cobra" ) var upgradeCmd = &cobra.Command{ - Use: "upgrade ", - Short: "Upgrade a stack", - Long: `Upgrade a stack by pulling newer images. - This operation will restart the stack if running. + Use: "upgrade ", + Short: "Upgrade a stack to different version", + Long: `Upgrade a stack by pulling updated images. + This operation will stop the stack if running. If certain containers were pinned to a specific image at init, this command will have no effect on those containers.`, + Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { + var spin *spinner.Spinner + if fancyFeatures && !verbose { + spin = spinner.New(spinner.CharSets[11], 100*time.Millisecond) + logger = log.NewSpinnerLogger(spin) + } ctx := log.WithVerbosity(context.Background(), verbose) ctx = log.WithLogger(ctx, logger) + + dockerVersion, err := docker.CheckDockerConfig() + if err != nil { + return err + } + ctx = context.WithValue(ctx, docker.CtxComposeVersionKey{}, dockerVersion) + stackManager := stacks.NewStackManager(ctx) if len(args) == 0 { return fmt.Errorf("no stack specified") } stackName := args[0] + if len(args) <= 1 { + return fmt.Errorf("no version specified") + } + version := args[1] if err := stackManager.LoadStack(stackName); err != nil { return err } fmt.Printf("upgrading stack '%s'... ", stackName) - if err := stackManager.UpgradeStack(); err != nil { + if err := stackManager.UpgradeStack(version); err != nil { return err } - fmt.Printf("done\n\nYour stack has been upgraded. To start your upgraded stack run:\n\n%s start %s\n\n", rootCmd.Use, stackName) + fmt.Printf("\n\nYour stack has been upgraded to %s\n\nTo start your upgraded stack run:\n\n%s start %s\n\n", version, rootCmd.Use, stackName) return nil }, } diff --git a/internal/core/config.go b/internal/core/config.go index 0281a1d3..d62b2dae 100644 --- a/internal/core/config.go +++ b/internal/core/config.go @@ -162,7 +162,7 @@ func getPostgresURL(member *types.Organization) string { func getSQLitePath(member *types.Organization, runtimeDir string) string { if !member.External { - return "/etc/firefly/db?_busy_timeout=5000" + return "/etc/firefly/db/sqlite.db?_busy_timeout=5000" } else { return path.Join(runtimeDir, member.ID+".db") } diff --git a/internal/docker/docker_config.go b/internal/docker/docker_config.go index 30a0f35e..f1ac02ca 100644 --- a/internal/docker/docker_config.go +++ b/internal/docker/docker_config.go @@ -95,10 +95,14 @@ func CreateDockerCompose(s *types.Stack) *DockerComposeConfig { fmt.Sprintf("%d:%d", member.ExposedFireflyPort, member.ExposedFireflyPort), fmt.Sprintf("%d:%d", member.ExposedFireflyAdminSPIPort, member.ExposedFireflyAdminSPIPort), }, - Volumes: []string{fmt.Sprintf("%s:/etc/firefly/firefly.core.yml:ro", configFile)}, + Volumes: []string{ + fmt.Sprintf("%s:/etc/firefly/firefly.core.yml:ro", configFile), + fmt.Sprintf("firefly_core_db_%s:/etc/firefly/db", member.ID), + }, DependsOn: map[string]map[string]string{}, Logging: StandardLogOptions, } + compose.Volumes[fmt.Sprintf("firefly_core_db_%s", member.ID)] = struct{}{} compose.Services["firefly_core_"+member.ID].DependsOn["dataexchange_"+member.ID] = map[string]string{"condition": "service_started"} compose.Services["firefly_core_"+member.ID].DependsOn["ipfs_"+member.ID] = map[string]string{"condition": "service_healthy"} } diff --git a/internal/log/spin.go b/internal/log/spin.go index 9a21ea86..e3a7357d 100644 --- a/internal/log/spin.go +++ b/internal/log/spin.go @@ -1,4 +1,4 @@ -// Copyright © 2021 Kaleido, Inc. +// Copyright © 2023 Kaleido, Inc. // // SPDX-License-Identifier: Apache-2.0 // diff --git a/internal/stacks/stack_manager.go b/internal/stacks/stack_manager.go index 5760570d..fc6c21d3 100644 --- a/internal/stacks/stack_manager.go +++ b/internal/stacks/stack_manager.go @@ -418,10 +418,7 @@ func (s *StackManager) writeStackConfig() error { if err != nil { return err } - if err := ioutil.WriteFile(filepath.Join(s.Stack.StackDir, "stack.json"), stackConfigBytes, 0755); err != nil { - return err - } - return s.writeStackStateJSON(s.Stack.InitDir) + return ioutil.WriteFile(filepath.Join(s.Stack.StackDir, "stack.json"), stackConfigBytes, 0755) } func (s *StackManager) writeConfig(options *types.InitOptions) error { @@ -459,6 +456,9 @@ func (s *StackManager) writeConfig(options *types.InitOptions) error { if err := s.writeStackConfig(); err != nil { return err } + if err := s.writeStackStateJSON(s.Stack.InitDir); err != nil { + return err + } if err := s.blockchainProvider.WriteConfig(options); err != nil { return err @@ -1013,11 +1013,73 @@ func (s *StackManager) waitForFireflyStart(port int) error { return fmt.Errorf("waited for %v seconds for firefly to start on port %v but it was never available", retries*retryPeriod/1000, port) } -func (s *StackManager) UpgradeStack() error { - if err := s.runDockerComposeCommand("down"); err != nil { +func (s *StackManager) UpgradeStack(version string) error { + // stop the currently running stack + if err := s.StopStack(); err != nil { + return err + } + oldManifest := s.Stack.VersionManifest + + // get the version manifest for the new version + newManifest, err := core.GetManifestForRelease(version) + if err != nil { + return err + } + + if err := replaceVersions(oldManifest, newManifest, filepath.Join(s.Stack.StackDir, "docker-compose.yml")); err != nil { + return err + } + + s.Stack.VersionManifest = newManifest + s.writeStackConfig() + + if err := s.PullStack(&types.PullOptions{}); err != nil { return err } - return s.runDockerComposeCommand("pull") + + return nil +} + +func replaceVersions(oldManifest, newManifest *types.VersionManifest, filename string) error { + b, err := ioutil.ReadFile(filename) + if err != nil { + return err + } + s := string(b) + + old := oldManifest.FireFly.GetDockerImageString() + new := newManifest.FireFly.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + old = oldManifest.Ethconnect.GetDockerImageString() + new = newManifest.Ethconnect.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + old = oldManifest.Evmconnect.GetDockerImageString() + new = newManifest.Evmconnect.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + old = oldManifest.Fabconnect.GetDockerImageString() + new = newManifest.Fabconnect.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + old = oldManifest.DataExchange.GetDockerImageString() + new = newManifest.DataExchange.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + old = oldManifest.TokensERC1155.GetDockerImageString() + new = newManifest.TokensERC1155.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + old = oldManifest.TokensERC20ERC721.GetDockerImageString() + new = newManifest.TokensERC20ERC721.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + old = oldManifest.Signer.GetDockerImageString() + new = newManifest.Signer.GetDockerImageString() + s = strings.Replace(s, old, new, -1) + + return ioutil.WriteFile(filename, []byte(s), 0755) } func (s *StackManager) PrintStackInfo() error {