From efb8683da6c175cd8f94b2814eb7650715702124 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 16:42:54 +0800 Subject: [PATCH 01/24] dapr airgap mode Signed-off-by: Ian Luo --- .gitignore | 3 + Makefile | 26 +++ cmd/init.go | 9 + pkg/standalone/common.go | 114 +++++++++++++ pkg/standalone/docker.go | 109 ++++++++++++ pkg/standalone/embed.go | 17 ++ pkg/standalone/noembed.go | 11 ++ pkg/standalone/stage.go | 184 ++++++++++++++++++++ pkg/standalone/standalone.go | 313 ++++++++++++++++------------------- 9 files changed, 619 insertions(+), 167 deletions(-) create mode 100644 pkg/standalone/docker.go create mode 100644 pkg/standalone/embed.go create mode 100644 pkg/standalone/noembed.go create mode 100644 pkg/standalone/stage.go diff --git a/.gitignore b/.gitignore index 7097dd727..fb7c13358 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ test_output.json # Go Workspaces (introduced in Go 1.18+) go.work + +# Downloaded artifacts in airgap mode +pkg/standalone/staging/ diff --git a/Makefile b/Makefile index c9f1b135e..f6cf32a64 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,8 @@ GIT_COMMIT = $(shell git rev-list -1 HEAD) GIT_VERSION = $(shell git describe --always --abbrev=7 --dirty) CGO ?= 0 CLI_BINARY = dapr +AIRGAP = airgap +CLI_BINARY_AIRGAP = $(CLI_BINARY)_$(AIRGAP) ifdef REL_VERSION CLI_VERSION := $(REL_VERSION) @@ -84,6 +86,8 @@ else $(info $(H) Build with debugger information) endif +TAGFLAGS=-tags embed + ################################################################################ # Go build details # ################################################################################ @@ -104,6 +108,14 @@ $(CLI_BINARY): CGO_ENABLED=$(CGO) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(GCFLAGS) -ldflags $(LDFLAGS) \ -o $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT); +.PHONY: build-$(AIRGAP) +build-$(AIRGAP): $(CLI_BINARY_AIRGAP) + +$(CLI_BINARY_AIRGAP): $(CLI_BINARY) + $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT) init --staging + CGO_ENABLED=$(CGO) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(TAGFLAGS) $(GCFLAGS) -ldflags $(LDFLAGS) \ + -o $(BINS_OUT_DIR)/$(CLI_BINARY_AIRGAP)$(BINARY_EXT); + ################################################################################ # Target: lint # ################################################################################ @@ -127,12 +139,26 @@ archive-$(CLI_BINARY).tar.gz: tar czf "$(ARCHIVE_OUT_DIR)/$(CLI_BINARY)_$(GOOS)_$(GOARCH)$(ARCHIVE_EXT)" -C "$(BINS_OUT_DIR)" "$(CLI_BINARY)$(BINARY_EXT)" endif +archive-$(AIRGAP): archive-$(CLI_BINARY_AIRGAP)$(ARCHIVE_EXT) +ifeq ($(GOOS),windows) +archive-$(CLI_BINARY_AIRGAP).zip: + 7z.exe a -tzip "$(ARCHIVE_OUT_DIR)\\$(CLI_BINARY_AIRGAP)_$(GOOS)_$(GOARCH)$(ARCHIVE_EXT)" "$(BINS_OUT_DIR)\\$(CLI_BINARY_AIRGAP)$(BINARY_EXT)" +else +archive-$(CLI_BINARY_AIRGAP).tar.gz: + chmod +x $(BINS_OUT_DIR)/$(CLI_BINARY_AIRGAP)$(BINARY_EXT) + tar czf "$(ARCHIVE_OUT_DIR)/$(CLI_BINARY_AIRGAP)_$(GOOS)_$(GOARCH)$(ARCHIVE_EXT)" -C "$(BINS_OUT_DIR)" "$(CLI_BINARY_AIRGAP)$(BINARY_EXT)" +endif + + ################################################################################ # Target: release # ################################################################################ .PHONY: release release: build archive +.PHONY: release-$(AIRGAP) +release-$(AIRGAP): build-$(AIRGAP) archive-$(AIRGAP) + .PHONY: test-deps test-deps: # The desire here is to download this test dependency without polluting go.mod diff --git a/cmd/init.go b/cmd/init.go index 2d367e8e6..adbe4605c 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -36,6 +36,7 @@ var ( enableMTLS bool enableHA bool values []string + staging bool ) var InitCmd = &cobra.Command{ @@ -90,6 +91,13 @@ dapr init -s os.Exit(1) } print.SuccessStatusEvent(os.Stdout, fmt.Sprintf("Success! Dapr has been installed to namespace %s. To verify, run `dapr status -k' in your terminal. To get started, go here: https://aka.ms/dapr-getting-started", config.Namespace)) + } else if staging { + err := standalone.Stage(runtimeVersion, dashboardVersion) + if err != nil { + print.FailureStatusEvent(os.Stderr, err.Error()) + os.Exit(1) + } + print.SuccessStatusEvent(os.Stdout, "Success! Dapr binaries is prepared.") } else { dockerNetwork := "" imageRepositoryURL := "" @@ -131,6 +139,7 @@ func init() { InitCmd.Flags().BoolVarP(&enableHA, "enable-ha", "", false, "Enable high availability (HA) mode") InitCmd.Flags().String("network", "", "The Docker network on which to deploy the Dapr runtime") InitCmd.Flags().BoolP("help", "h", false, "Print this help message") + InitCmd.Flags().BoolVarP(&staging, "staging", "", false, "Packaging Dapr relevant artifacts into this binary (aka airgap mode)") InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") InitCmd.Flags().String("image-repository", "", "Custom/Private docker image repository url") RootCmd.AddCommand(InitCmd) diff --git a/pkg/standalone/common.go b/pkg/standalone/common.go index e81e1f6f7..693e52c51 100644 --- a/pkg/standalone/common.go +++ b/pkg/standalone/common.go @@ -14,9 +14,16 @@ limitations under the License. package standalone import ( + "fmt" + "github.com/dapr/cli/pkg/print" + cli_ver "github.com/dapr/cli/pkg/version" + "io" + "net/http" "os" + "path" path_filepath "path/filepath" "runtime" + "strings" ) const ( @@ -50,3 +57,110 @@ func DefaultComponentsDirPath() string { func DefaultConfigFilePath() string { return path_filepath.Join(defaultDaprDirPath(), defaultConfigFileName) } + +func findDashboardVersion(ver string) string { + if isEmbedded { + return dashboardVersion + } + + if ver == latestVersion { + v, err := cli_ver.GetDashboardVersion() + if err != nil { + print.WarningStatusEvent(os.Stdout, "cannot get the latest dashboard version: '%s'. Try specifying --dashboard-version=", err) + print.WarningStatusEvent(os.Stdout, "continuing, but dashboard will be unavailable") + } + return v + } + + return ver +} + +func findRuntimeVersion(ver string) (string, error) { + if isEmbedded { + return runtimeVersion, nil + } + + if ver == latestVersion { + v, err := cli_ver.GetDaprVersion() + if err != nil { + return "", fmt.Errorf("cannot get the latest release version: '%s'. Try specifying --runtime-version=", err) + } + return v, nil + } + return ver, nil +} + +func prepareDaprInstallDir(daprBinDir string) error { + err := os.MkdirAll(daprBinDir, 0777) + if err != nil { + return err + } + + err = os.Chmod(daprBinDir, 0777) + if err != nil { + return err + } + + return nil +} + +func archiveExt() string { + ext := "tar.gz" + if runtime.GOOS == daprWindowsOS { + ext = "zip" + } + + return ext +} + +func downloadBinary(dir, version, binaryFilePrefix, githubRepo string) (string, error) { + fileURL := fmt.Sprintf( + "https://github.com/%s/%s/releases/download/v%s/%s", + cli_ver.DaprGitHubOrg, + githubRepo, + version, + binaryName(binaryFilePrefix)) + + return downloadFile(dir, fileURL) +} + +func binaryName(binaryFilePrefix string) string { + return fmt.Sprintf("%s_%s_%s.%s", binaryFilePrefix, runtime.GOOS, runtime.GOARCH, archiveExt()) +} + +// nolint:gosec +func downloadFile(dir string, url string) (string, error) { + tokens := strings.Split(url, "/") + fileName := tokens[len(tokens)-1] + + filepath := path.Join(dir, fileName) + _, err := os.Stat(filepath) + if os.IsExist(err) { + return "", nil + } + + resp, err := http.Get(url) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode == 404 { + return "", fmt.Errorf("version not found from url: %s", url) + } else if resp.StatusCode != 200 { + return "", fmt.Errorf("download failed with %d", resp.StatusCode) + } + + out, err := os.Create(filepath) + if err != nil { + return "", err + } + defer out.Close() + + _, err = io.Copy(out, resp.Body) + if err != nil { + return "", err + } + + return filepath, nil +} diff --git a/pkg/standalone/docker.go b/pkg/standalone/docker.go new file mode 100644 index 000000000..4e5efc4bd --- /dev/null +++ b/pkg/standalone/docker.go @@ -0,0 +1,109 @@ +package standalone + +import ( + "fmt" + "github.com/dapr/cli/utils" + "io" + "os" + "os/exec" + path_filepath "path/filepath" + "strings" +) + +func loadDocker(in io.Reader) error { + subProcess := exec.Command("docker", "load") + + stdin, err := subProcess.StdinPipe() + if err != nil { + return err + } + defer stdin.Close() + + subProcess.Stdout = os.Stdout + subProcess.Stderr = os.Stderr + + if err = subProcess.Start(); err != nil { + return err + } + + if _, err = io.Copy(stdin, in); err != nil { + return err + } + + stdin.Close() + + if err = subProcess.Wait(); err != nil { + return err + } + + return nil +} + +func loadDockerIfNecessary(dockerImage string) error { + if !isEmbedded { + return nil + } + + var imageFile io.Reader + var err error + imageFile, err = binaries.Open(path_filepath.Join("staging", "images", imageFileName(dockerImage))) + if err != nil { + return fmt.Errorf("fail to read docker image file %s: %v", dockerImage, err) + } + err = loadDocker(imageFile) + if err != nil { + return fmt.Errorf("fail to load docker image %s: %v", dockerImage, err) + } + + return nil +} + +// check if the container either exists and stopped or is running. +func confirmContainerIsRunningOrExists(containerName string, isRunning bool) (bool, error) { + // e.g. docker ps --filter name=dapr_redis --filter status=running --format {{.Names}} + + args := []string{"ps", "--all", "--filter", "name=" + containerName} + + if isRunning { + args = append(args, "--filter", "status=running") + } + + args = append(args, "--format", "{{.Names}}") + response, err := utils.RunCmdAndWait("docker", args...) + response = strings.TrimSuffix(response, "\n") + + // If 'docker ps' failed due to some reason + if err != nil { + return false, fmt.Errorf("unable to confirm whether %s is running or exists. error\n%v", containerName, err.Error()) + } + // 'docker ps' worked fine, but the response did not have the container name + if response == "" || response != containerName { + if isRunning { + return false, fmt.Errorf("container %s is not running", containerName) + } + return false, nil + } + + return true, nil +} + +func isContainerRunError(err error) bool { + if exitError, ok := err.(*exec.ExitError); ok { + exitCode := exitError.ExitCode() + return exitCode == 125 + } + return false +} + +func parseDockerError(component string, err error) error { + if exitError, ok := err.(*exec.ExitError); ok { + exitCode := exitError.ExitCode() + if exitCode == 125 { // see https://github.com/moby/moby/pull/14012 + return fmt.Errorf("failed to launch %s. Is it already running?", component) + } + if exitCode == 127 { + return fmt.Errorf("failed to launch %s. Make sure Docker is installed and running", component) + } + } + return err +} diff --git a/pkg/standalone/embed.go b/pkg/standalone/embed.go new file mode 100644 index 000000000..d9a0d2191 --- /dev/null +++ b/pkg/standalone/embed.go @@ -0,0 +1,17 @@ +//go:build embed +// +build embed + +package standalone + +import "embed" + +//go:embed staging +var binaries embed.FS + +//go:embed staging/runtime.ver +var runtimeVersion string + +//go:embed staging/dashboard.ver +var dashboardVersion string + +var isEmbedded = true diff --git a/pkg/standalone/noembed.go b/pkg/standalone/noembed.go new file mode 100644 index 000000000..5f78da82f --- /dev/null +++ b/pkg/standalone/noembed.go @@ -0,0 +1,11 @@ +//go:build !embed +// +build !embed + +package standalone + +import "embed" + +var binaries embed.FS +var runtimeVersion string +var dashboardVersion string +var isEmbedded = false diff --git a/pkg/standalone/stage.go b/pkg/standalone/stage.go new file mode 100644 index 000000000..f188393b7 --- /dev/null +++ b/pkg/standalone/stage.go @@ -0,0 +1,184 @@ +package standalone + +import ( + "errors" + "fmt" + "github.com/dapr/cli/pkg/print" + cli_ver "github.com/dapr/cli/pkg/version" + "github.com/dapr/cli/utils" + "os" + path_filepath "path/filepath" + "strings" + "sync" +) + +const ( + stagingBaseDir = "pkg/standalone/staging" + runtimeVerFile = "runtime.ver" + dashboardVerFile = "dashboard.ver" +) + +var ( + stagingBinDir = path_filepath.Join(stagingBaseDir, defaultDaprBinDirName) +) + +func Stage(rv, dv string) error { + dockerInstalled := utils.IsDockerInstalled() + if !dockerInstalled { + return errors.New("could not connect to Docker. Docker may not be installed or running") + } + + var err error + + runtimeVersion, err = findRuntimeVersion(rv) + if err != nil { + return err + } + print.InfoStatusEvent(os.Stdout, "Staging runtime version %s", runtimeVersion) + dashboardVersion = findDashboardVersion(dv) + + err = prepareDaprInstallDir(stagingBinDir) + if err != nil { + return err + } + + err = writeVersions(runtimeVersion, dashboardVersion) + if err != nil { + return err + } + + var wg sync.WaitGroup + errorChan := make(chan error) + initSteps := []func(*sync.WaitGroup, chan<- error){ + saveDaprImage, + saveRedisImage, + saveZipkinImage, + downloadDaprd, + downloadDashboard, + downloadPlacement, + } + + wg.Add(len(initSteps)) + + msg := "Downloading binaries and images..." + stopSpinning := print.Spinner(os.Stdout, msg) + defer stopSpinning(print.Failure) + + for _, step := range initSteps { + // Run init on the configurations and containers + go step(&wg, errorChan) + } + + go func() { + wg.Wait() + close(errorChan) + }() + + for err = range errorChan { + if err != nil { + return err + } + } + + stopSpinning(print.Success) + + msg = "Dapr binaries and images are downloaded." + print.SuccessStatusEvent(os.Stdout, msg) + print.InfoStatusEvent(os.Stdout, "%s binary has been installed to %s.", daprRuntimeFilePrefix, stagingBinDir) + return nil +} + +func downloadDaprd(wg *sync.WaitGroup, errorChan chan<- error) { + defer wg.Done() + _, err := downloadBinary(stagingBinDir, runtimeVersion, daprRuntimeFilePrefix, cli_ver.DaprGitHubRepo) + errorChan <- err +} + +func downloadDashboard(wg *sync.WaitGroup, errorChan chan<- error) { + defer wg.Done() + _, err := downloadBinary(stagingBinDir, dashboardVersion, dashboardFilePrefix, cli_ver.DashboardGitHubRepo) + errorChan <- err +} + +func downloadPlacement(wg *sync.WaitGroup, errorChan chan<- error) { + defer wg.Done() + _, err := downloadBinary(stagingBinDir, runtimeVersion, placementServiceFilePrefix, cli_ver.DaprGitHubRepo) + errorChan <- err +} + +func saveDaprImage(wg *sync.WaitGroup, errorChan chan<- error) { + defer wg.Done() + image := fmt.Sprintf("%s:%s", daprDockerImageName, runtimeVersion) + // Use only image for latest version + if runtimeVersion == latestVersion { + image = daprDockerImageName + } + + errorChan <- saveImage(image) +} + +func saveZipkinImage(wg *sync.WaitGroup, errorChan chan<- error) { + defer wg.Done() + errorChan <- saveImage(zipkinDockerImageName) +} + +func saveRedisImage(wg *sync.WaitGroup, errorChan chan<- error) { + defer wg.Done() + errorChan <- saveImage(redisDockerImageName) +} + +func saveImage(image string) error { + _, err := utils.RunCmdAndWait("docker", "pull", image) + if err != nil { + return err + } + + imageDir := path_filepath.Join("pkg/standalone/staging", "images") + err = prepareDaprInstallDir(imageDir) + if err != nil { + return err + } + + filename := imageFileName(image) + _, err = utils.RunCmdAndWait("docker", "save", "-o", path_filepath.Join(imageDir, filename), image) + return err +} + +func imageFileName(image string) string { + filename := image + ".tar.gz" + filename = strings.ReplaceAll(filename, "/", "-") + filename = strings.ReplaceAll(filename, ":", "-") + return filename +} + +func writeVersions(runtimeVersion, dashboardVersion string) error { + err := writeFile(path_filepath.Join(stagingBaseDir, runtimeVerFile), runtimeVersion) + if err != nil { + return err + } + + err = writeFile(path_filepath.Join(stagingBaseDir, dashboardVerFile), dashboardVersion) + if err != nil { + return err + } + + return nil +} + +func writeFile(filePath string, content string) error { + f, err := os.Create(filePath) + defer f.Close() + + if err != nil { + print.WarningStatusEvent(os.Stdout, "cannot create %s: %v", filePath, err) + return err + } + + _, err = f.WriteString(content) + if err != nil { + print.WarningStatusEvent(os.Stdout, "cannot write %s: %v", filePath, err) + return err + } + + return nil +} diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index bbe5434fe..163701b47 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -16,14 +16,14 @@ package standalone import ( "archive/tar" "archive/zip" + "bytes" "compress/gzip" "errors" "fmt" "io" + "io/fs" "io/ioutil" - "net/http" "os" - "os/exec" "path" path_filepath "path/filepath" "runtime" @@ -108,7 +108,7 @@ func isBinaryInstallationRequired(binaryFilePrefix, installDir string) (bool, er } // Init installs Dapr on a local machine using the supplied runtimeVersion. -func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRepositoryURL string) error { +func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL string) error { if !slimMode { dockerInstalled := utils.IsDockerInstalled() if !dockerInstalled { @@ -116,27 +116,22 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod } } - if runtimeVersion == latestVersion { - var err error - runtimeVersion, err = cli_ver.GetDaprVersion() - if err != nil { - return fmt.Errorf("cannot get the latest release version: '%s'. Try specifying --runtime-version=", err) - } + var err error + runtimeVersion, err = findRuntimeVersion(rv) + if err != nil { + return err } print.InfoStatusEvent(os.Stdout, "Installing runtime version %s", runtimeVersion) - if dashboardVersion == latestVersion { - var err error - dashboardVersion, err = cli_ver.GetDashboardVersion() - if err != nil { - print.WarningStatusEvent(os.Stdout, "cannot get the latest dashboard version: '%s'. Try specifying --dashboard-version=", err) - print.WarningStatusEvent(os.Stdout, "continuing, but dashboard will be unavailable") - } + dashboardVersion = findDashboardVersion(dv) + + if isEmbedded { + print.InfoStatusEvent(os.Stdout, "Init dapr with embedded binaries") } daprBinDir := defaultDaprBinPath() - err := prepareDaprInstallDir(daprBinDir) + err = prepareDaprInstallDir(daprBinDir) if err != nil { return err } @@ -148,7 +143,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod var wg sync.WaitGroup errorChan := make(chan error) - initSteps := []func(*sync.WaitGroup, chan<- error, string, string, string, string){} + var initSteps []func(*sync.WaitGroup, chan<- error, string, string) if slimMode { // Install 3 binaries in slim mode: daprd, dashboard, placement wg.Add(3) @@ -167,6 +162,9 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod wg.Add(len(initSteps)) msg := "Downloading binaries and setting up components..." + if isEmbedded { + msg = "Extracting binaries and setting up components..." + } stopSpinning := print.Spinner(os.Stdout, msg) defer stopSpinning(print.Failure) @@ -191,7 +189,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod for _, step := range initSteps { // Run init on the configurations and containers - go step(&wg, errorChan, daprBinDir, runtimeVersion, dockerNetwork, imageRepositoryURL) + go step(&wg, errorChan, dockerNetwork, imageRepositoryURL) } go func() { @@ -208,7 +206,10 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod stopSpinning(print.Success) msg = "Downloaded binaries and completed components set up." - print.SuccessStatusEvent(os.Stdout, msg) + if isEmbedded { + msg = "Extracted binaries and completed components set up." + } + print.SuccessStatusEvent(os.Stdout, "Downloaded binaries and completed components set up.") print.InfoStatusEvent(os.Stdout, "%s binary has been installed to %s.", daprRuntimeFilePrefix, daprBinDir) if slimMode { // Print info on placement binary only on slim install @@ -230,21 +231,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod return nil } -func prepareDaprInstallDir(daprBinDir string) error { - err := os.MkdirAll(daprBinDir, 0777) - if err != nil { - return err - } - - err = os.Chmod(daprBinDir, 0777) - if err != nil { - return err - } - - return nil -} - -func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dir, version string, dockerNetwork string, imageRepositoryURL string) { +func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, imageRepositoryURL string) { defer wg.Done() zipkinContainerName := utils.CreateContainerName(DaprZipkinContainerName, dockerNetwork) @@ -260,6 +247,12 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dir, version string, // do not create container again if it exists args = append(args, "start", zipkinContainerName) } else { + err = loadDockerIfNecessary(zipkinDockerImageName) + if err != nil { + errorChan <- err + return + } + imageName := zipkinDockerImageName if imageRepositoryURL != "" { imageName = fmt.Sprintf("%s/%s", imageRepositoryURL, imageName) @@ -298,7 +291,7 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dir, version string, errorChan <- nil } -func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dir, version string, dockerNetwork string, imageRepositoryURL string) { +func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, imageRepositoryURL string) { defer wg.Done() redisContainerName := utils.CreateContainerName(DaprRedisContainerName, dockerNetwork) @@ -313,6 +306,12 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dir, version string, d // do not create container again if it exists args = append(args, "start", redisContainerName) } else { + err = loadDockerIfNecessary(redisDockerImageName) + if err != nil { + errorChan <- err + return + } + imageName := redisDockerImageName if imageRepositoryURL != "" { imageName = fmt.Sprintf("%s/%s", imageRepositoryURL, imageName) @@ -350,67 +349,17 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dir, version string, d errorChan <- nil } -// check if the container either exists and stopped or is running. -func confirmContainerIsRunningOrExists(containerName string, isRunning bool) (bool, error) { - // e.g. docker ps --filter name=dapr_redis --filter status=running --format {{.Names}} - - args := []string{"ps", "--all", "--filter", "name=" + containerName} - - if isRunning { - args = append(args, "--filter", "status=running") - } - - args = append(args, "--format", "{{.Names}}") - response, err := utils.RunCmdAndWait("docker", args...) - response = strings.TrimSuffix(response, "\n") - - // If 'docker ps' failed due to some reason - if err != nil { - return false, fmt.Errorf("unable to confirm whether %s is running or exists. error\n%v", containerName, err.Error()) - } - // 'docker ps' worked fine, but the response did not have the container name - if response == "" || response != containerName { - if isRunning { - return false, fmt.Errorf("container %s is not running", containerName) - } - return false, nil - } - - return true, nil -} - -func parseDockerError(component string, err error) error { - if exitError, ok := err.(*exec.ExitError); ok { - exitCode := exitError.ExitCode() - if exitCode == 125 { // see https://github.com/moby/moby/pull/14012 - return fmt.Errorf("failed to launch %s. Is it already running?", component) - } - if exitCode == 127 { - return fmt.Errorf("failed to launch %s. Make sure Docker is installed and running", component) - } - } - return err -} - -func isContainerRunError(err error) bool { - if exitError, ok := err.(*exec.ExitError); ok { - exitCode := exitError.ExitCode() - return exitCode == 125 - } - return false -} - -func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, dir, version string, dockerNetwork string, imageRepositoryURL string) { +func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, imageRepositoryURL string) { defer wg.Done() placementContainerName := utils.CreateContainerName(DaprPlacementContainerName, dockerNetwork) - image := fmt.Sprintf("%s:%s", daprDockerImageName, version) + image := fmt.Sprintf("%s:%s", daprDockerImageName, runtimeVersion) if imageRepositoryURL != "" { image = fmt.Sprintf("%s/%s", imageRepositoryURL, image) } // Use only image for latest version - if version == latestVersion { + if runtimeVersion == latestVersion { image = daprDockerImageName } @@ -424,6 +373,12 @@ func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, dir, versio return } + err = loadDockerIfNecessary(image) + if err != nil { + errorChan <- err + return + } + args := []string{ "run", "--name", placementContainerName, @@ -495,42 +450,20 @@ func moveDashboardFiles(extractedFilePath string, dir string) (string, error) { func installBinary(wg *sync.WaitGroup, errorChan chan<- error, dir, version, binaryFilePrefix string, dockerNetwork string, githubRepo string) { defer wg.Done() - archiveExt := "tar.gz" - - if runtime.GOOS == daprWindowsOS { - archiveExt = "zip" - } - - fileURL := fmt.Sprintf( - "https://github.com/%s/%s/releases/download/v%s/%s_%s_%s.%s", - cli_ver.DaprGitHubOrg, - githubRepo, - version, - binaryFilePrefix, - runtime.GOOS, - runtime.GOARCH, - archiveExt) - - filepath, err := downloadFile(dir, fileURL) - if err != nil { - errorChan <- fmt.Errorf("error downloading %s binary: %s", binaryFilePrefix, err) - return - } - extractedFilePath := "" + var err error + var filepath = "" - if archiveExt == "zip" { - extractedFilePath, err = unzip(filepath, dir, binaryFilePrefix) - } else { - extractedFilePath, err = untar(filepath, dir, binaryFilePrefix) - } - if err != nil { - errorChan <- fmt.Errorf("error extracting %s binary: %s", binaryFilePrefix, err) - return + if !isEmbedded { + filepath, err = downloadBinary(dir, version, binaryFilePrefix, githubRepo) + if err != nil { + errorChan <- fmt.Errorf("error downloading %s binary: %s", binaryFilePrefix, err) + return + } } - err = os.Remove(filepath) + extractedFilePath, err := extractFile(filepath, dir, binaryFilePrefix) if err != nil { - errorChan <- fmt.Errorf("failed to remove archive: %s", err) + errorChan <- err return } @@ -557,7 +490,7 @@ func installBinary(wg *sync.WaitGroup, errorChan chan<- error, dir, version, bin errorChan <- nil } -func createComponentsAndConfiguration(wg *sync.WaitGroup, errorChan chan<- error, _, _ string, dockerNetwork string, _ string) { +func createComponentsAndConfiguration(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, _ string) { defer wg.Done() redisHost := daprDefaultHost @@ -589,7 +522,7 @@ func createComponentsAndConfiguration(wg *sync.WaitGroup, errorChan chan<- error } } -func createSlimConfiguration(wg *sync.WaitGroup, errorChan chan<- error, _, _ string, _ string, _ string) { +func createSlimConfiguration(wg *sync.WaitGroup, errorChan chan<- error, _ string, _ string) { defer wg.Done() // For --slim we pass empty string so that we do not configure zipkin. @@ -635,13 +568,81 @@ func sanitizeExtractPath(destination string, filePath string) (string, error) { return destpath, nil } -func unzip(filepath, targetDir, binaryFilePrefix string) (string, error) { +func extractFile(filepath, dir, binaryFilePrefix string) (string, error) { + var extractFunc func(string, string, string) (string, error) + if archiveExt() == "zip" { + if !isEmbedded { + extractFunc = unzipExternalFile + } else { + extractFunc = unzipEmbeddedFile + } + } else { + if !isEmbedded { + extractFunc = untarExternalFile + } else { + extractFunc = untarEmbeddedFile + } + } + + extractedFilePath, err := extractFunc(filepath, dir, binaryFilePrefix) + if err != nil { + return "", fmt.Errorf("error extracting %s binary: %s", binaryFilePrefix, err) + } + + if !isEmbedded { + err = os.Remove(filepath) + if err != nil { + return "", fmt.Errorf("failed to remove archive: %s", err) + } + } + + return extractedFilePath, nil +} + +func unzipEmbeddedFile(filepath, dir, binaryFilePrefix string) (string, error) { + file := binaryStagePath(binaryFilePrefix) + f, err := binaries.Open(file) + if err != nil { + return "", fmt.Errorf("error open embedded file %s: %s", file, err) + } + defer f.Close() + + var fi fs.FileInfo + fi, err = f.Stat() + if err != nil { + return "", fmt.Errorf("error stat embedded file %s: %s", file, err) + } + + var fileBytes []byte + fileBytes, err = io.ReadAll(f) + if err != nil { + return "", fmt.Errorf("error read embedded file %s: %s", file, err) + } + + var reader *zip.Reader + reader, err = zip.NewReader(bytes.NewReader(fileBytes), fi.Size()) + if err != nil { + return "", fmt.Errorf("error open embedded zip file %s: %s", file, err) + } + + return unzip(reader, dir, binaryFilePrefix) +} + +func binaryStagePath(binaryFilePrefix string) string { + return path.Join("staging", defaultDaprBinDirName, binaryName(binaryFilePrefix)) +} + +func unzipExternalFile(filepath, dir, binaryFilePrefix string) (string, error) { r, err := zip.OpenReader(filepath) if err != nil { - return "", err + return "", fmt.Errorf("error open zip file %s: %s", filepath, err) } defer r.Close() + return unzip(&r.Reader, dir, binaryFilePrefix) +} + +func unzip(r *zip.Reader, targetDir string, binaryFilePrefix string) (string, error) { foundBinary := "" for _, f := range r.File { fpath, err := sanitizeExtractPath(targetDir, f.Name) @@ -685,14 +686,29 @@ func unzip(filepath, targetDir, binaryFilePrefix string) (string, error) { return foundBinary, nil } -func untar(filepath, targetDir, binaryFilePrefix string) (string, error) { - tarFile, err := os.Open(filepath) +func untarEmbeddedFile(filepath, dir, binaryFilePrefix string) (string, error) { + file := binaryStagePath(binaryFilePrefix) + reader, err := binaries.Open(file) if err != nil { - return "", err + return "", fmt.Errorf("error open embedded file %s: %s", file, err) } - defer tarFile.Close() + defer reader.Close() - gzr, err := gzip.NewReader(tarFile) + return untar(reader, dir, binaryFilePrefix) +} + +func untarExternalFile(filepath, dir, binaryFilePrefix string) (string, error) { + reader, err := os.Open(filepath) + if err != nil { + return "", fmt.Errorf("error open tar gz file %s: %s", filepath, err) + } + defer reader.Close() + + return untar(reader, dir, binaryFilePrefix) +} + +func untar(reader io.Reader, targetDir string, binaryFilePrefix string) (string, error) { + gzr, err := gzip.NewReader(reader) if err != nil { return "", err } @@ -794,43 +810,6 @@ func moveFileToPath(filepath string, installLocation string) (string, error) { return destFilePath, nil } -// nolint:gosec -func downloadFile(dir string, url string) (string, error) { - tokens := strings.Split(url, "/") - fileName := tokens[len(tokens)-1] - - filepath := path.Join(dir, fileName) - _, err := os.Stat(filepath) - if os.IsExist(err) { - return "", nil - } - - resp, err := http.Get(url) - if err != nil { - return "", err - } - defer resp.Body.Close() - - if resp.StatusCode == 404 { - return "", fmt.Errorf("version not found from url: %s", url) - } else if resp.StatusCode != 200 { - return "", fmt.Errorf("download failed with %d", resp.StatusCode) - } - - out, err := os.Create(filepath) - if err != nil { - return "", err - } - defer out.Close() - - _, err = io.Copy(out, resp.Body) - if err != nil { - return "", err - } - - return filepath, nil -} - func createRedisStateStore(redisHost string, componentsPath string) error { redisStore := component{ APIVersion: "dapr.io/v1alpha1", From f27fedf9adc24d9cd027e37914a4f04112137c0d Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 17:03:27 +0800 Subject: [PATCH 02/24] fix lint issue Signed-off-by: Ian Luo --- pkg/standalone/common.go | 9 +++++---- pkg/standalone/docker.go | 3 ++- pkg/standalone/stage.go | 11 +++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/pkg/standalone/common.go b/pkg/standalone/common.go index 693e52c51..168ca192a 100644 --- a/pkg/standalone/common.go +++ b/pkg/standalone/common.go @@ -15,8 +15,6 @@ package standalone import ( "fmt" - "github.com/dapr/cli/pkg/print" - cli_ver "github.com/dapr/cli/pkg/version" "io" "net/http" "os" @@ -24,6 +22,9 @@ import ( path_filepath "path/filepath" "runtime" "strings" + + "github.com/dapr/cli/pkg/print" + cli_ver "github.com/dapr/cli/pkg/version" ) const ( @@ -91,12 +92,12 @@ func findRuntimeVersion(ver string) (string, error) { } func prepareDaprInstallDir(daprBinDir string) error { - err := os.MkdirAll(daprBinDir, 0777) + err := os.MkdirAll(daprBinDir, 0o777) if err != nil { return err } - err = os.Chmod(daprBinDir, 0777) + err = os.Chmod(daprBinDir, 0o777) if err != nil { return err } diff --git a/pkg/standalone/docker.go b/pkg/standalone/docker.go index 4e5efc4bd..5a873603f 100644 --- a/pkg/standalone/docker.go +++ b/pkg/standalone/docker.go @@ -2,12 +2,13 @@ package standalone import ( "fmt" - "github.com/dapr/cli/utils" "io" "os" "os/exec" path_filepath "path/filepath" "strings" + + "github.com/dapr/cli/utils" ) func loadDocker(in io.Reader) error { diff --git a/pkg/standalone/stage.go b/pkg/standalone/stage.go index f188393b7..12108157e 100644 --- a/pkg/standalone/stage.go +++ b/pkg/standalone/stage.go @@ -3,13 +3,14 @@ package standalone import ( "errors" "fmt" - "github.com/dapr/cli/pkg/print" - cli_ver "github.com/dapr/cli/pkg/version" - "github.com/dapr/cli/utils" "os" path_filepath "path/filepath" "strings" "sync" + + "github.com/dapr/cli/pkg/print" + cli_ver "github.com/dapr/cli/pkg/version" + "github.com/dapr/cli/utils" ) const ( @@ -18,9 +19,7 @@ const ( dashboardVerFile = "dashboard.ver" ) -var ( - stagingBinDir = path_filepath.Join(stagingBaseDir, defaultDaprBinDirName) -) +var stagingBinDir = path_filepath.Join(stagingBaseDir, defaultDaprBinDirName) func Stage(rv, dv string) error { dockerInstalled := utils.IsDockerInstalled() From 199e90613debfa18c1c59649c75a11d11531247f Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 17:19:43 +0800 Subject: [PATCH 03/24] fix lint issue Signed-off-by: Ian Luo --- pkg/standalone/noembed.go | 10 ++++++---- pkg/standalone/stage.go | 4 +++- pkg/standalone/standalone.go | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pkg/standalone/noembed.go b/pkg/standalone/noembed.go index 5f78da82f..95bf807bc 100644 --- a/pkg/standalone/noembed.go +++ b/pkg/standalone/noembed.go @@ -5,7 +5,9 @@ package standalone import "embed" -var binaries embed.FS -var runtimeVersion string -var dashboardVersion string -var isEmbedded = false +var ( + binaries embed.FS + runtimeVersion string + dashboardVersion string + isEmbedded = false +) diff --git a/pkg/standalone/stage.go b/pkg/standalone/stage.go index 12108157e..b5ce5e478 100644 --- a/pkg/standalone/stage.go +++ b/pkg/standalone/stage.go @@ -166,7 +166,9 @@ func writeVersions(runtimeVersion, dashboardVersion string) error { func writeFile(filePath string, content string) error { f, err := os.Create(filePath) - defer f.Close() + defer func() { + _ = f.Close() + }() if err != nil { print.WarningStatusEvent(os.Stdout, "cannot create %s: %v", filePath, err) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 163701b47..3d138de7c 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -209,7 +209,7 @@ func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL if isEmbedded { msg = "Extracted binaries and completed components set up." } - print.SuccessStatusEvent(os.Stdout, "Downloaded binaries and completed components set up.") + print.SuccessStatusEvent(os.Stdout, msg) print.InfoStatusEvent(os.Stdout, "%s binary has been installed to %s.", daprRuntimeFilePrefix, daprBinDir) if slimMode { // Print info on placement binary only on slim install From 2154f3a09869b737e0db222a103e893a7a623b90 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 17:29:46 +0800 Subject: [PATCH 04/24] fix lint issue Signed-off-by: Ian Luo --- pkg/standalone/standalone.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 3d138de7c..105adafeb 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -450,8 +450,10 @@ func moveDashboardFiles(extractedFilePath string, dir string) (string, error) { func installBinary(wg *sync.WaitGroup, errorChan chan<- error, dir, version, binaryFilePrefix string, dockerNetwork string, githubRepo string) { defer wg.Done() - var err error - var filepath = "" + var ( + err error + filepath string + ) if !isEmbedded { filepath, err = downloadBinary(dir, version, binaryFilePrefix, githubRepo) From 8e94ae5195cade34aa5f53f6355854365238ca5b Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 17:41:51 +0800 Subject: [PATCH 05/24] update github workflow to build dapr-airgap binary Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index 9276c1b8c..dfbe8341b 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -88,6 +88,7 @@ jobs: run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} + make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Create release_version.txt if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' run: | From 11ff72b5d54b23596caed6241407f49de5c23a89 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 18:50:22 +0800 Subject: [PATCH 06/24] chmod +x before execute dapr Signed-off-by: Ian Luo --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f6cf32a64..2ff240142 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ GIT_COMMIT = $(shell git rev-list -1 HEAD) GIT_VERSION = $(shell git describe --always --abbrev=7 --dirty) CGO ?= 0 CLI_BINARY = dapr -AIRGAP = airgap +AIRGAP = airgap CLI_BINARY_AIRGAP = $(CLI_BINARY)_$(AIRGAP) ifdef REL_VERSION @@ -112,6 +112,7 @@ $(CLI_BINARY): build-$(AIRGAP): $(CLI_BINARY_AIRGAP) $(CLI_BINARY_AIRGAP): $(CLI_BINARY) + chmod +x $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT) $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT) init --staging CGO_ENABLED=$(CGO) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(TAGFLAGS) $(GCFLAGS) -ldflags $(LDFLAGS) \ -o $(BINS_OUT_DIR)/$(CLI_BINARY_AIRGAP)$(BINARY_EXT); From 8645c62eb4d4f63ec57b55f487e7e66f813f8a72 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 19:26:42 +0800 Subject: [PATCH 07/24] relies on running dapr on the right arch, remove it from workflow Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index dfbe8341b..9276c1b8c 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -88,7 +88,6 @@ jobs: run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Create release_version.txt if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' run: | From ee8e14f4d86b5aa8fc107ee787de692ee9429d5c Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 19:45:25 +0800 Subject: [PATCH 08/24] run make release-airgap only on linux amd64 Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index 9276c1b8c..a558fff6f 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -88,6 +88,11 @@ jobs: run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} + - name: Run make release-airgap to build and archive all-in-one binaries + if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' + run: | + mkdir -p ${{ env.ARCHIVE_OUTDIR }} + make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Create release_version.txt if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' run: | From a30a523f3e3601471a53e1d142057d29c52c8287 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 19:52:19 +0800 Subject: [PATCH 09/24] enhance workflow and makefile Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 2 +- Makefile | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index a558fff6f..cab1873e9 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -89,7 +89,7 @@ jobs: mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Run make release-airgap to build and archive all-in-one binaries - if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' + if: matrix.target_arch == 'amd64' run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} diff --git a/Makefile b/Makefile index 2ff240142..263952940 100644 --- a/Makefile +++ b/Makefile @@ -112,10 +112,9 @@ $(CLI_BINARY): build-$(AIRGAP): $(CLI_BINARY_AIRGAP) $(CLI_BINARY_AIRGAP): $(CLI_BINARY) - chmod +x $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT) $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT) init --staging CGO_ENABLED=$(CGO) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(TAGFLAGS) $(GCFLAGS) -ldflags $(LDFLAGS) \ - -o $(BINS_OUT_DIR)/$(CLI_BINARY_AIRGAP)$(BINARY_EXT); + -o $(BINS_OUT_DIR)/$(CLI_BINARY_AIRGAP)$(BINARY_EXT) ################################################################################ # Target: lint # From cd569a39035cea5334f8d63fc8b0b6f9052df07b Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 20:03:52 +0800 Subject: [PATCH 10/24] exclude darwin since no docker's available Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index cab1873e9..52f518c31 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -89,7 +89,7 @@ jobs: mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Run make release-airgap to build and archive all-in-one binaries - if: matrix.target_arch == 'amd64' + if: matrix.target_arch == 'amd64' && metrix.target_os != 'darwin' run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} From a1aabaf784e8557c67871ffc054f7f9db07e6564 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 20:31:16 +0800 Subject: [PATCH 11/24] fix typo Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index 52f518c31..50f26a3f8 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -89,7 +89,7 @@ jobs: mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Run make release-airgap to build and archive all-in-one binaries - if: matrix.target_arch == 'amd64' && metrix.target_os != 'darwin' + if: matrix.target_arch == 'amd64' && matrix.target_os != 'darwin' run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} From eaa54e2d0cd8298a66cf39525b05fd9cf0111037 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Feb 2022 20:39:56 +0800 Subject: [PATCH 12/24] mkdir -p cannot repeat on windows Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index 50f26a3f8..74da51764 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -91,7 +91,6 @@ jobs: - name: Run make release-airgap to build and archive all-in-one binaries if: matrix.target_arch == 'amd64' && matrix.target_os != 'darwin' run: | - mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Create release_version.txt if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' From f75999c0089375fded1bac299ff01848d8076ec4 Mon Sep 17 00:00:00 2001 From: "beiwei.ly" Date: Thu, 24 Feb 2022 15:54:58 +0800 Subject: [PATCH 13/24] introduce --from-dir to support init from local disk Signed-off-by: beiwei.ly --- .github/scripts/archive_dapr_artifacts.sh | 167 +++++++++ .github/workflows/dapr_cli.yaml | 7 +- .gitignore | 3 - Makefile | 26 -- cmd/init.go | 13 +- pkg/standalone/common.go | 115 ------ pkg/standalone/docker.go | 19 +- pkg/standalone/embed.go | 17 - pkg/standalone/noembed.go | 13 - pkg/standalone/stage.go | 185 ---------- pkg/standalone/standalone.go | 416 ++++++++++++++-------- 11 files changed, 451 insertions(+), 530 deletions(-) create mode 100755 .github/scripts/archive_dapr_artifacts.sh delete mode 100644 pkg/standalone/embed.go delete mode 100644 pkg/standalone/noembed.go delete mode 100644 pkg/standalone/stage.go diff --git a/.github/scripts/archive_dapr_artifacts.sh b/.github/scripts/archive_dapr_artifacts.sh new file mode 100755 index 000000000..269015ad0 --- /dev/null +++ b/.github/scripts/archive_dapr_artifacts.sh @@ -0,0 +1,167 @@ +#!/usr/bin/env bash + +# ------------------------------------------------------------ +# Copyright 2021 The Dapr Authors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file_base except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ------------------------------------------------------------ + +# Http request CLI +DAPR_HTTP_REQUEST_CLI=curl + +# GitHub Organization and repo name to download release +GITHUB_ORG=dapr +GITHUB_DAPR_REPO=dapr +GITHUB_DASHBOARD_REPO=dashboard + +# Dapr binaries filename +DAPRD_FILENAME=daprd +PLACEMENT_FILENAME=placement +DASHBOARD_FILENAME=dashboard + +checkHttpRequestCLI() { + if type "curl" > /dev/null; then + DAPR_HTTP_REQUEST_CLI=curl + elif type "wget" > /dev/null; then + DAPR_HTTP_REQUEST_CLI=wget + else + echo "Either curl or wget is required" + exit 1 + fi +} + +getLatestRelease() { + local daprReleaseUrl="https://api.github.com/repos/${GITHUB_ORG}/$1/releases" + local latest_release="" + + if [ "$DAPR_HTTP_REQUEST_CLI" == "curl" ]; then + latest_release=$(curl -s $daprReleaseUrl | grep \"tag_name\" | grep -v rc | awk 'NR==1{print $2}' | sed -n 's/\"\(.*\)\",/\1/p') + else + latest_release=$(wget -q --header="Accept: application/json" -O - $daprReleaseUrl | grep \"tag_name\" | grep -v rc | awk 'NR==1{print $2}' | sed -n 's/\"\(.*\)\",/\1/p') + fi + + echo $latest_release +} + +downloadFile() { + local repo=$1 + local file_base=$2 + local ver=$3 + local platform=$4 + local ext="tar.gz" + local out_dir=${TARGET_DIR}/dist + + if [[ "${platform}" == "windows_amd64" ]]; then + ext="zip" + fi + + local filename=${file_base}_${platform}.${ext} + local download_url="https://github.com/${GITHUB_ORG}/${repo}/releases/download/${ver}/${filename}" + + mkdir -p ${out_dir} + + echo "Downloading $download_url to ${out_dir}/${filename}..." + if [ "$DAPR_HTTP_REQUEST_CLI" == "curl" ]; then + curl -SsL "$download_url" -o "${out_dir}/${filename}" + else + wget -q -O "${out_dir}/${filename}" "$download_url" + fi + + if [ ! -f "${out_dir}/${filename}" ]; then + echo "failed to download $download_url ..." + exit 1 + fi +} + +downloadDockerImage() { + local image_name=$1 + local image_ver=$2 + local docker_image="${image_name}:${image_ver}" + if [[ ${image_ver} == "latest" ]]; then + docker_image=${image_name} + fi + local file_name=$(echo ${docker_image} | sed -e 's/\//-/g' | sed -e 's/:/-/g').tar.gz + local out_dir=${TARGET_DIR}/docker + + mkdir -p ${out_dir} + + echo "Pulling docker image ${docker_image}..." + docker pull "${docker_image}" + echo "Saving docker image to ${out_dir}/${file_name}..." + docker save -o "${out_dir}/${file_name}" "${docker_image}" +} + +downloadArtifacts() { + for platform in "darwin_amd64" "darwin_arm64" "linux_amd64" "linux_arm64" "windows_amd64"; do + downloadFile ${GITHUB_DAPR_REPO} ${DAPRD_FILENAME} ${RUNTIME_VER} ${platform} + downloadFile ${GITHUB_DAPR_REPO} ${PLACEMENT_FILENAME} ${RUNTIME_VER} ${platform} + downloadFile ${GITHUB_DASHBOARD_REPO} ${DASHBOARD_FILENAME} ${DASHBOARD_VER} ${platform} + done +} + +downloadDockerImages() { + downloadDockerImage "daprio/dapr" $(echo ${RUNTIME_VER} | sed -e 's/^v//') + downloadDockerImage "openzipkin/zipkin" "latest" + downloadDockerImage "redis" "latest" +} + +writeVersion() { + local runtime_ver=$(echo ${RUNTIME_VER} | sed -e 's/^v//') + local dashboard_ver=$(echo ${DASHBOARD_VER} | sed -e 's/^v//') + cat < ${TARGET_DIR}/version.json +{ + "daprd": "${runtime_ver}", + "dashboard": "${dashboard_ver}" +} +VERSION +} + +fail_trap() { + result=$? + if [ "$result" != "0" ]; then + echo "Failed to download Dapr artifacts" + echo "For support, go to https://dapr.io" + fi + exit $result +} + +# ----------------------------------------------------------------------------- +# main +# ----------------------------------------------------------------------------- +trap "fail_trap" EXIT + +while getopts 'r:d:o:' options; do + case ${options} in + r) RUNTIME_VER=${OPTARG};; + d) DASHBOARD_VER=${OPTARG};; + o) TARGET_DIR=${OPTARG};; + esac +done + +checkHttpRequestCLI + +if [[ -z ${RUNTIME_VER} ]]; then + RUNTIME_VER=$(getLatestRelease ${GITHUB_DAPR_REPO}) +fi + +if [[ -z ${DASHBOARD_VER} ]]; then + DASHBOARD_VER=$(getLatestRelease ${GITHUB_DASHBOARD_REPO}) +fi + +if [[ -z ${TARGET_DIR} ]]; then + TARGET_DIR=artifacts +fi + +mkdir -p ${TARGET_DIR} +writeVersion +downloadArtifacts +downloadDockerImages + + diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index 74da51764..83184e575 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -88,10 +88,11 @@ jobs: run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - - name: Run make release-airgap to build and archive all-in-one binaries - if: matrix.target_arch == 'amd64' && matrix.target_os != 'darwin' + - name: Run archive_dapr_artifacts.sh to archive Dapr artificats + if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' run: | - make release-airgap GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} + sh ./.github/scripts/archive_dapr_artifacts.sh -o dapr_artifacts + tar czf ${{ env.ARCHIVE_OUTDIR }}/dapr_artifacts.tar.gz -C dapr_artifacts dist docker - name: Create release_version.txt if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' run: | diff --git a/.gitignore b/.gitignore index fb7c13358..7097dd727 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,3 @@ test_output.json # Go Workspaces (introduced in Go 1.18+) go.work - -# Downloaded artifacts in airgap mode -pkg/standalone/staging/ diff --git a/Makefile b/Makefile index 263952940..c9f1b135e 100644 --- a/Makefile +++ b/Makefile @@ -22,8 +22,6 @@ GIT_COMMIT = $(shell git rev-list -1 HEAD) GIT_VERSION = $(shell git describe --always --abbrev=7 --dirty) CGO ?= 0 CLI_BINARY = dapr -AIRGAP = airgap -CLI_BINARY_AIRGAP = $(CLI_BINARY)_$(AIRGAP) ifdef REL_VERSION CLI_VERSION := $(REL_VERSION) @@ -86,8 +84,6 @@ else $(info $(H) Build with debugger information) endif -TAGFLAGS=-tags embed - ################################################################################ # Go build details # ################################################################################ @@ -108,14 +104,6 @@ $(CLI_BINARY): CGO_ENABLED=$(CGO) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(GCFLAGS) -ldflags $(LDFLAGS) \ -o $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT); -.PHONY: build-$(AIRGAP) -build-$(AIRGAP): $(CLI_BINARY_AIRGAP) - -$(CLI_BINARY_AIRGAP): $(CLI_BINARY) - $(BINS_OUT_DIR)/$(CLI_BINARY)$(BINARY_EXT) init --staging - CGO_ENABLED=$(CGO) GOOS=$(GOOS) GOARCH=$(GOARCH) go build $(TAGFLAGS) $(GCFLAGS) -ldflags $(LDFLAGS) \ - -o $(BINS_OUT_DIR)/$(CLI_BINARY_AIRGAP)$(BINARY_EXT) - ################################################################################ # Target: lint # ################################################################################ @@ -139,26 +127,12 @@ archive-$(CLI_BINARY).tar.gz: tar czf "$(ARCHIVE_OUT_DIR)/$(CLI_BINARY)_$(GOOS)_$(GOARCH)$(ARCHIVE_EXT)" -C "$(BINS_OUT_DIR)" "$(CLI_BINARY)$(BINARY_EXT)" endif -archive-$(AIRGAP): archive-$(CLI_BINARY_AIRGAP)$(ARCHIVE_EXT) -ifeq ($(GOOS),windows) -archive-$(CLI_BINARY_AIRGAP).zip: - 7z.exe a -tzip "$(ARCHIVE_OUT_DIR)\\$(CLI_BINARY_AIRGAP)_$(GOOS)_$(GOARCH)$(ARCHIVE_EXT)" "$(BINS_OUT_DIR)\\$(CLI_BINARY_AIRGAP)$(BINARY_EXT)" -else -archive-$(CLI_BINARY_AIRGAP).tar.gz: - chmod +x $(BINS_OUT_DIR)/$(CLI_BINARY_AIRGAP)$(BINARY_EXT) - tar czf "$(ARCHIVE_OUT_DIR)/$(CLI_BINARY_AIRGAP)_$(GOOS)_$(GOARCH)$(ARCHIVE_EXT)" -C "$(BINS_OUT_DIR)" "$(CLI_BINARY_AIRGAP)$(BINARY_EXT)" -endif - - ################################################################################ # Target: release # ################################################################################ .PHONY: release release: build archive -.PHONY: release-$(AIRGAP) -release-$(AIRGAP): build-$(AIRGAP) archive-$(AIRGAP) - .PHONY: test-deps test-deps: # The desire here is to download this test dependency without polluting go.mod diff --git a/cmd/init.go b/cmd/init.go index adbe4605c..83473cc35 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -36,7 +36,7 @@ var ( enableMTLS bool enableHA bool values []string - staging bool + fromDir string ) var InitCmd = &cobra.Command{ @@ -91,13 +91,6 @@ dapr init -s os.Exit(1) } print.SuccessStatusEvent(os.Stdout, fmt.Sprintf("Success! Dapr has been installed to namespace %s. To verify, run `dapr status -k' in your terminal. To get started, go here: https://aka.ms/dapr-getting-started", config.Namespace)) - } else if staging { - err := standalone.Stage(runtimeVersion, dashboardVersion) - if err != nil { - print.FailureStatusEvent(os.Stderr, err.Error()) - os.Exit(1) - } - print.SuccessStatusEvent(os.Stdout, "Success! Dapr binaries is prepared.") } else { dockerNetwork := "" imageRepositoryURL := "" @@ -105,7 +98,7 @@ dapr init -s dockerNetwork = viper.GetString("network") imageRepositoryURL = viper.GetString("image-repository") } - err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRepositoryURL) + err := standalone.Init(runtimeVersion, dashboardVersion, dockerNetwork, slimMode, imageRepositoryURL, fromDir) if err != nil { print.FailureStatusEvent(os.Stderr, err.Error()) os.Exit(1) @@ -138,8 +131,8 @@ func init() { InitCmd.Flags().BoolVarP(&enableMTLS, "enable-mtls", "", true, "Enable mTLS in your cluster") InitCmd.Flags().BoolVarP(&enableHA, "enable-ha", "", false, "Enable high availability (HA) mode") InitCmd.Flags().String("network", "", "The Docker network on which to deploy the Dapr runtime") + InitCmd.Flags().StringVarP(&fromDir, "from-dir", "", "artifacts", "Use Dapr artifacts from local directory instead of from network to init") InitCmd.Flags().BoolP("help", "h", false, "Print this help message") - InitCmd.Flags().BoolVarP(&staging, "staging", "", false, "Packaging Dapr relevant artifacts into this binary (aka airgap mode)") InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") InitCmd.Flags().String("image-repository", "", "Custom/Private docker image repository url") RootCmd.AddCommand(InitCmd) diff --git a/pkg/standalone/common.go b/pkg/standalone/common.go index 168ca192a..e81e1f6f7 100644 --- a/pkg/standalone/common.go +++ b/pkg/standalone/common.go @@ -14,17 +14,9 @@ limitations under the License. package standalone import ( - "fmt" - "io" - "net/http" "os" - "path" path_filepath "path/filepath" "runtime" - "strings" - - "github.com/dapr/cli/pkg/print" - cli_ver "github.com/dapr/cli/pkg/version" ) const ( @@ -58,110 +50,3 @@ func DefaultComponentsDirPath() string { func DefaultConfigFilePath() string { return path_filepath.Join(defaultDaprDirPath(), defaultConfigFileName) } - -func findDashboardVersion(ver string) string { - if isEmbedded { - return dashboardVersion - } - - if ver == latestVersion { - v, err := cli_ver.GetDashboardVersion() - if err != nil { - print.WarningStatusEvent(os.Stdout, "cannot get the latest dashboard version: '%s'. Try specifying --dashboard-version=", err) - print.WarningStatusEvent(os.Stdout, "continuing, but dashboard will be unavailable") - } - return v - } - - return ver -} - -func findRuntimeVersion(ver string) (string, error) { - if isEmbedded { - return runtimeVersion, nil - } - - if ver == latestVersion { - v, err := cli_ver.GetDaprVersion() - if err != nil { - return "", fmt.Errorf("cannot get the latest release version: '%s'. Try specifying --runtime-version=", err) - } - return v, nil - } - return ver, nil -} - -func prepareDaprInstallDir(daprBinDir string) error { - err := os.MkdirAll(daprBinDir, 0o777) - if err != nil { - return err - } - - err = os.Chmod(daprBinDir, 0o777) - if err != nil { - return err - } - - return nil -} - -func archiveExt() string { - ext := "tar.gz" - if runtime.GOOS == daprWindowsOS { - ext = "zip" - } - - return ext -} - -func downloadBinary(dir, version, binaryFilePrefix, githubRepo string) (string, error) { - fileURL := fmt.Sprintf( - "https://github.com/%s/%s/releases/download/v%s/%s", - cli_ver.DaprGitHubOrg, - githubRepo, - version, - binaryName(binaryFilePrefix)) - - return downloadFile(dir, fileURL) -} - -func binaryName(binaryFilePrefix string) string { - return fmt.Sprintf("%s_%s_%s.%s", binaryFilePrefix, runtime.GOOS, runtime.GOARCH, archiveExt()) -} - -// nolint:gosec -func downloadFile(dir string, url string) (string, error) { - tokens := strings.Split(url, "/") - fileName := tokens[len(tokens)-1] - - filepath := path.Join(dir, fileName) - _, err := os.Stat(filepath) - if os.IsExist(err) { - return "", nil - } - - resp, err := http.Get(url) - if err != nil { - return "", err - } - defer resp.Body.Close() - - if resp.StatusCode == 404 { - return "", fmt.Errorf("version not found from url: %s", url) - } else if resp.StatusCode != 200 { - return "", fmt.Errorf("download failed with %d", resp.StatusCode) - } - - out, err := os.Create(filepath) - if err != nil { - return "", err - } - defer out.Close() - - _, err = io.Copy(out, resp.Body) - if err != nil { - return "", err - } - - return filepath, nil -} diff --git a/pkg/standalone/docker.go b/pkg/standalone/docker.go index 5a873603f..13b888e18 100644 --- a/pkg/standalone/docker.go +++ b/pkg/standalone/docker.go @@ -11,7 +11,7 @@ import ( "github.com/dapr/cli/utils" ) -func loadDocker(in io.Reader) error { +func runDockerLoad(in io.Reader) error { subProcess := exec.Command("docker", "load") stdin, err := subProcess.StdinPipe() @@ -40,18 +40,14 @@ func loadDocker(in io.Reader) error { return nil } -func loadDockerIfNecessary(dockerImage string) error { - if !isEmbedded { - return nil - } - +func loadDocker(dir string, dockerImage string) error { var imageFile io.Reader var err error - imageFile, err = binaries.Open(path_filepath.Join("staging", "images", imageFileName(dockerImage))) + imageFile, err = os.Open(path_filepath.Join(dir, imageFileName(dockerImage))) if err != nil { return fmt.Errorf("fail to read docker image file %s: %v", dockerImage, err) } - err = loadDocker(imageFile) + err = runDockerLoad(imageFile) if err != nil { return fmt.Errorf("fail to load docker image %s: %v", dockerImage, err) } @@ -108,3 +104,10 @@ func parseDockerError(component string, err error) error { } return err } + +func imageFileName(image string) string { + filename := image + ".tar.gz" + filename = strings.ReplaceAll(filename, "/", "-") + filename = strings.ReplaceAll(filename, ":", "-") + return filename +} diff --git a/pkg/standalone/embed.go b/pkg/standalone/embed.go deleted file mode 100644 index d9a0d2191..000000000 --- a/pkg/standalone/embed.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build embed -// +build embed - -package standalone - -import "embed" - -//go:embed staging -var binaries embed.FS - -//go:embed staging/runtime.ver -var runtimeVersion string - -//go:embed staging/dashboard.ver -var dashboardVersion string - -var isEmbedded = true diff --git a/pkg/standalone/noembed.go b/pkg/standalone/noembed.go deleted file mode 100644 index 95bf807bc..000000000 --- a/pkg/standalone/noembed.go +++ /dev/null @@ -1,13 +0,0 @@ -//go:build !embed -// +build !embed - -package standalone - -import "embed" - -var ( - binaries embed.FS - runtimeVersion string - dashboardVersion string - isEmbedded = false -) diff --git a/pkg/standalone/stage.go b/pkg/standalone/stage.go deleted file mode 100644 index b5ce5e478..000000000 --- a/pkg/standalone/stage.go +++ /dev/null @@ -1,185 +0,0 @@ -package standalone - -import ( - "errors" - "fmt" - "os" - path_filepath "path/filepath" - "strings" - "sync" - - "github.com/dapr/cli/pkg/print" - cli_ver "github.com/dapr/cli/pkg/version" - "github.com/dapr/cli/utils" -) - -const ( - stagingBaseDir = "pkg/standalone/staging" - runtimeVerFile = "runtime.ver" - dashboardVerFile = "dashboard.ver" -) - -var stagingBinDir = path_filepath.Join(stagingBaseDir, defaultDaprBinDirName) - -func Stage(rv, dv string) error { - dockerInstalled := utils.IsDockerInstalled() - if !dockerInstalled { - return errors.New("could not connect to Docker. Docker may not be installed or running") - } - - var err error - - runtimeVersion, err = findRuntimeVersion(rv) - if err != nil { - return err - } - print.InfoStatusEvent(os.Stdout, "Staging runtime version %s", runtimeVersion) - dashboardVersion = findDashboardVersion(dv) - - err = prepareDaprInstallDir(stagingBinDir) - if err != nil { - return err - } - - err = writeVersions(runtimeVersion, dashboardVersion) - if err != nil { - return err - } - - var wg sync.WaitGroup - errorChan := make(chan error) - initSteps := []func(*sync.WaitGroup, chan<- error){ - saveDaprImage, - saveRedisImage, - saveZipkinImage, - downloadDaprd, - downloadDashboard, - downloadPlacement, - } - - wg.Add(len(initSteps)) - - msg := "Downloading binaries and images..." - stopSpinning := print.Spinner(os.Stdout, msg) - defer stopSpinning(print.Failure) - - for _, step := range initSteps { - // Run init on the configurations and containers - go step(&wg, errorChan) - } - - go func() { - wg.Wait() - close(errorChan) - }() - - for err = range errorChan { - if err != nil { - return err - } - } - - stopSpinning(print.Success) - - msg = "Dapr binaries and images are downloaded." - print.SuccessStatusEvent(os.Stdout, msg) - print.InfoStatusEvent(os.Stdout, "%s binary has been installed to %s.", daprRuntimeFilePrefix, stagingBinDir) - return nil -} - -func downloadDaprd(wg *sync.WaitGroup, errorChan chan<- error) { - defer wg.Done() - _, err := downloadBinary(stagingBinDir, runtimeVersion, daprRuntimeFilePrefix, cli_ver.DaprGitHubRepo) - errorChan <- err -} - -func downloadDashboard(wg *sync.WaitGroup, errorChan chan<- error) { - defer wg.Done() - _, err := downloadBinary(stagingBinDir, dashboardVersion, dashboardFilePrefix, cli_ver.DashboardGitHubRepo) - errorChan <- err -} - -func downloadPlacement(wg *sync.WaitGroup, errorChan chan<- error) { - defer wg.Done() - _, err := downloadBinary(stagingBinDir, runtimeVersion, placementServiceFilePrefix, cli_ver.DaprGitHubRepo) - errorChan <- err -} - -func saveDaprImage(wg *sync.WaitGroup, errorChan chan<- error) { - defer wg.Done() - image := fmt.Sprintf("%s:%s", daprDockerImageName, runtimeVersion) - // Use only image for latest version - if runtimeVersion == latestVersion { - image = daprDockerImageName - } - - errorChan <- saveImage(image) -} - -func saveZipkinImage(wg *sync.WaitGroup, errorChan chan<- error) { - defer wg.Done() - errorChan <- saveImage(zipkinDockerImageName) -} - -func saveRedisImage(wg *sync.WaitGroup, errorChan chan<- error) { - defer wg.Done() - errorChan <- saveImage(redisDockerImageName) -} - -func saveImage(image string) error { - _, err := utils.RunCmdAndWait("docker", "pull", image) - if err != nil { - return err - } - - imageDir := path_filepath.Join("pkg/standalone/staging", "images") - err = prepareDaprInstallDir(imageDir) - if err != nil { - return err - } - - filename := imageFileName(image) - _, err = utils.RunCmdAndWait("docker", "save", "-o", path_filepath.Join(imageDir, filename), image) - return err -} - -func imageFileName(image string) string { - filename := image + ".tar.gz" - filename = strings.ReplaceAll(filename, "/", "-") - filename = strings.ReplaceAll(filename, ":", "-") - return filename -} - -func writeVersions(runtimeVersion, dashboardVersion string) error { - err := writeFile(path_filepath.Join(stagingBaseDir, runtimeVerFile), runtimeVersion) - if err != nil { - return err - } - - err = writeFile(path_filepath.Join(stagingBaseDir, dashboardVerFile), dashboardVersion) - if err != nil { - return err - } - - return nil -} - -func writeFile(filePath string, content string) error { - f, err := os.Create(filePath) - defer func() { - _ = f.Close() - }() - - if err != nil { - print.WarningStatusEvent(os.Stdout, "cannot create %s: %v", filePath, err) - return err - } - - _, err = f.WriteString(content) - if err != nil { - print.WarningStatusEvent(os.Stdout, "cannot write %s: %v", filePath, err) - return err - } - - return nil -} diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 105adafeb..241678b71 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -16,13 +16,13 @@ package standalone import ( "archive/tar" "archive/zip" - "bytes" "compress/gzip" + "encoding/json" "errors" "fmt" "io" - "io/fs" "io/ioutil" + "net/http" "os" "path" path_filepath "path/filepath" @@ -59,6 +59,9 @@ const ( DaprZipkinContainerName = "dapr_zipkin" errInstallTemplate = "please run `dapr uninstall` first before running `dapr init`" + + daprBinarySubDir = "dist" + dockerImageSubDir = "docker" ) type configuration struct { @@ -95,6 +98,15 @@ type componentMetadataItem struct { Value string `yaml:"value"` } +type initInfo struct { + fromDir string + slimMode bool + runtimeVersion string + dashboardVersion string + dockerNetwork string + imageRepositoryURL string +} + // Check if the previous version is already installed. func isBinaryInstallationRequired(binaryFilePrefix, installDir string) (bool, error) { binaryPath := binaryFilePath(installDir, binaryFilePrefix) @@ -108,7 +120,7 @@ func isBinaryInstallationRequired(binaryFilePrefix, installDir string) (bool, er } // Init installs Dapr on a local machine using the supplied runtimeVersion. -func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL string) error { +func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMode bool, imageRepositoryURL string, fromDir string) error { if !slimMode { dockerInstalled := utils.IsDockerInstalled() if !dockerInstalled { @@ -116,22 +128,34 @@ func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL } } - var err error - runtimeVersion, err = findRuntimeVersion(rv) - if err != nil { - return err + if runtimeVersion == latestVersion && fromDir == "" { + var err error + runtimeVersion, err = cli_ver.GetDaprVersion() + if err != nil { + return fmt.Errorf("cannot get the latest release version: '%s'. Try specifying --runtime-version=", err) + } } print.InfoStatusEvent(os.Stdout, "Installing runtime version %s", runtimeVersion) - dashboardVersion = findDashboardVersion(dv) + if dashboardVersion == latestVersion && fromDir == "" { + var err error + dashboardVersion, err = cli_ver.GetDashboardVersion() + if err != nil { + print.WarningStatusEvent(os.Stdout, "cannot get the latest dashboard version: '%s'. Try specifying --dashboard-version=", err) + print.WarningStatusEvent(os.Stdout, "continuing, but dashboard will be unavailable") + } + } - if isEmbedded { - print.InfoStatusEvent(os.Stdout, "Init dapr with embedded binaries") + if fromDir != "" { + v1, v2 := parseVersionFile(fromDir) + if v1 != "" && v2 != "" { + runtimeVersion, dashboardVersion = v1, v2 + } } daprBinDir := defaultDaprBinPath() - err = prepareDaprInstallDir(daprBinDir) + err := prepareDaprInstallDir(daprBinDir) if err != nil { return err } @@ -143,26 +167,22 @@ func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL var wg sync.WaitGroup errorChan := make(chan error) - var initSteps []func(*sync.WaitGroup, chan<- error, string, string) - if slimMode { - // Install 3 binaries in slim mode: daprd, dashboard, placement - wg.Add(3) - initSteps = append(initSteps, createSlimConfiguration) - } else if dashboardVersion != "" { - // Install 2 binaries: daprd, dashboard - wg.Add(2) - initSteps = append(initSteps, createComponentsAndConfiguration, runPlacementService, runRedis, runZipkin) - } else { - // Install 1 binaries: daprd - wg.Add(1) - initSteps = append(initSteps, createComponentsAndConfiguration, runPlacementService, runRedis, runZipkin) + var initSteps = []func(*sync.WaitGroup, chan<- error, initInfo){ + createSlimConfiguration, + createComponentsAndConfiguration, + installDaprRuntime, + installPlacement, + installDashboard, + runPlacementService, + runRedis, + runZipkin, } // Init other configurations, containers wg.Add(len(initSteps)) msg := "Downloading binaries and setting up components..." - if isEmbedded { + if fromDir != "" { msg = "Extracting binaries and setting up components..." } stopSpinning := print.Spinner(os.Stdout, msg) @@ -174,22 +194,17 @@ func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL return err } - // Initialize daprd binary - go installBinary(&wg, errorChan, daprBinDir, runtimeVersion, daprRuntimeFilePrefix, dockerNetwork, cli_ver.DaprGitHubRepo) - - // Initialize dashboard binary - if dashboardVersion != "" { - go installBinary(&wg, errorChan, daprBinDir, dashboardVersion, dashboardFilePrefix, dockerNetwork, cli_ver.DashboardGitHubRepo) - } - - if slimMode { - // Initialize placement binary only on slim install - go installBinary(&wg, errorChan, daprBinDir, runtimeVersion, placementServiceFilePrefix, dockerNetwork, cli_ver.DaprGitHubRepo) + info := initInfo{ + fromDir: fromDir, + slimMode: slimMode, + runtimeVersion: runtimeVersion, + dashboardVersion: dashboardVersion, + dockerNetwork: dockerNetwork, + imageRepositoryURL: imageRepositoryURL, } - for _, step := range initSteps { // Run init on the configurations and containers - go step(&wg, errorChan, dockerNetwork, imageRepositoryURL) + go step(&wg, errorChan, info) } go func() { @@ -206,7 +221,7 @@ func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL stopSpinning(print.Success) msg = "Downloaded binaries and completed components set up." - if isEmbedded { + if fromDir != "" { msg = "Extracted binaries and completed components set up." } print.SuccessStatusEvent(os.Stdout, msg) @@ -231,10 +246,14 @@ func Init(rv, dv string, dockerNetwork string, slimMode bool, imageRepositoryURL return nil } -func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, imageRepositoryURL string) { +func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() - zipkinContainerName := utils.CreateContainerName(DaprZipkinContainerName, dockerNetwork) + if info.slimMode { + return + } + + zipkinContainerName := utils.CreateContainerName(DaprZipkinContainerName, info.dockerNetwork) exists, err := confirmContainerIsRunningOrExists(zipkinContainerName, false) if err != nil { @@ -247,16 +266,20 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, // do not create container again if it exists args = append(args, "start", zipkinContainerName) } else { - err = loadDockerIfNecessary(zipkinDockerImageName) - if err != nil { - errorChan <- err - return + imageName := zipkinDockerImageName + if info.imageRepositoryURL != "" { + imageName = fmt.Sprintf("%s/%s", info.imageRepositoryURL, imageName) } - imageName := zipkinDockerImageName - if imageRepositoryURL != "" { - imageName = fmt.Sprintf("%s/%s", imageRepositoryURL, imageName) + if info.fromDir != "" { + dir := path_filepath.Join(info.fromDir, dockerImageSubDir) + err = loadDocker(dir, imageName) + if err != nil { + errorChan <- err + return + } } + args = append(args, "run", "--name", zipkinContainerName, @@ -264,10 +287,10 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, "-d", ) - if dockerNetwork != "" { + if info.dockerNetwork != "" { args = append( args, - "--network", dockerNetwork, + "--network", info.dockerNetwork, "--network-alias", DaprZipkinContainerName) } else { args = append( @@ -291,9 +314,14 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, errorChan <- nil } -func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, imageRepositoryURL string) { +func runRedis(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() - redisContainerName := utils.CreateContainerName(DaprRedisContainerName, dockerNetwork) + + if info.slimMode { + return + } + + redisContainerName := utils.CreateContainerName(DaprRedisContainerName, info.dockerNetwork) exists, err := confirmContainerIsRunningOrExists(redisContainerName, false) if err != nil { @@ -306,16 +334,20 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, // do not create container again if it exists args = append(args, "start", redisContainerName) } else { - err = loadDockerIfNecessary(redisDockerImageName) - if err != nil { - errorChan <- err - return + imageName := redisDockerImageName + if info.imageRepositoryURL != "" { + imageName = fmt.Sprintf("%s/%s", info.imageRepositoryURL, imageName) } - imageName := redisDockerImageName - if imageRepositoryURL != "" { - imageName = fmt.Sprintf("%s/%s", imageRepositoryURL, imageName) + if info.fromDir != "" { + dir := path_filepath.Join(info.fromDir, dockerImageSubDir) + err = loadDocker(dir, imageName) + if err != nil { + errorChan <- err + return + } } + args = append(args, "run", "--name", redisContainerName, @@ -323,10 +355,10 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, "-d", ) - if dockerNetwork != "" { + if info.dockerNetwork != "" { args = append( args, - "--network", dockerNetwork, + "--network", info.dockerNetwork, "--network-alias", DaprRedisContainerName) } else { args = append( @@ -349,17 +381,22 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, errorChan <- nil } -func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, imageRepositoryURL string) { +func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() - placementContainerName := utils.CreateContainerName(DaprPlacementContainerName, dockerNetwork) - image := fmt.Sprintf("%s:%s", daprDockerImageName, runtimeVersion) - if imageRepositoryURL != "" { - image = fmt.Sprintf("%s/%s", imageRepositoryURL, image) + if info.slimMode { + return + } + + placementContainerName := utils.CreateContainerName(DaprPlacementContainerName, info.dockerNetwork) + + image := fmt.Sprintf("%s:%s", daprDockerImageName, info.runtimeVersion) + if info.imageRepositoryURL != "" { + image = fmt.Sprintf("%s/%s", info.imageRepositoryURL, image) } // Use only image for latest version - if runtimeVersion == latestVersion { + if info.runtimeVersion == latestVersion { image = daprDockerImageName } @@ -373,10 +410,13 @@ func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwo return } - err = loadDockerIfNecessary(image) - if err != nil { - errorChan <- err - return + if info.fromDir != "" { + dir := path_filepath.Join(info.fromDir, dockerImageSubDir) + err = loadDocker(dir, image) + if err != nil { + errorChan <- err + return + } } args := []string{ @@ -387,9 +427,9 @@ func runPlacementService(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwo "--entrypoint", "./placement", } - if dockerNetwork != "" { + if info.dockerNetwork != "" { args = append(args, - "--network", dockerNetwork, + "--network", info.dockerNetwork, "--network-alias", DaprPlacementContainerName) } else { osPort := 50005 @@ -447,57 +487,98 @@ func moveDashboardFiles(extractedFilePath string, dir string) (string, error) { return extractedFilePath, nil } -func installBinary(wg *sync.WaitGroup, errorChan chan<- error, dir, version, binaryFilePrefix string, dockerNetwork string, githubRepo string) { +func installDaprRuntime(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() + err := installBinary(info.runtimeVersion, daprRuntimeFilePrefix, cli_ver.DaprGitHubRepo, info.fromDir) + if err != nil { + errorChan <- err + } +} + +func installDashboard(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { + defer wg.Done() + if info.dashboardVersion == "" { + return + } + + err := installBinary(info.dashboardVersion, dashboardFilePrefix, cli_ver.DashboardGitHubRepo, info.fromDir) + if err != nil { + errorChan <- err + } +} + +func installPlacement(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { + defer wg.Done() + + if !info.slimMode { + return + } + + err := installBinary(info.runtimeVersion, placementServiceFilePrefix, cli_ver.DaprGitHubRepo, info.fromDir) + if err != nil { + errorChan <- err + } +} + +func installBinary(version, binaryFilePrefix string, githubRepo string, fromDir string) error { var ( err error filepath string ) - if !isEmbedded { + dir := defaultDaprBinPath() + if fromDir == "" { filepath, err = downloadBinary(dir, version, binaryFilePrefix, githubRepo) if err != nil { - errorChan <- fmt.Errorf("error downloading %s binary: %s", binaryFilePrefix, err) - return + return fmt.Errorf("error downloading %s binary: %s", binaryFilePrefix, err) } + } else { + filepath = path_filepath.Join(fromDir, daprBinarySubDir, binaryName(binaryFilePrefix)) } extractedFilePath, err := extractFile(filepath, dir, binaryFilePrefix) if err != nil { - errorChan <- err - return + return err + } + + if fromDir == "" { + err = os.Remove(filepath) + if err != nil { + return fmt.Errorf("failed to remove archive: %s", err) + } } if binaryFilePrefix == "dashboard" { extractedFilePath, err = moveDashboardFiles(extractedFilePath, dir) if err != nil { - errorChan <- err - return + return err } } binaryPath, err := moveFileToPath(extractedFilePath, dir) if err != nil { - errorChan <- fmt.Errorf("error moving %s binary to path: %s", binaryFilePrefix, err) - return + return fmt.Errorf("error moving %s binary to path: %s", binaryFilePrefix, err) } err = makeExecutable(binaryPath) if err != nil { - errorChan <- fmt.Errorf("error making %s binary executable: %s", binaryFilePrefix, err) - return + return fmt.Errorf("error making %s binary executable: %s", binaryFilePrefix, err) } - errorChan <- nil + return nil } -func createComponentsAndConfiguration(wg *sync.WaitGroup, errorChan chan<- error, dockerNetwork string, _ string) { +func createComponentsAndConfiguration(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() + if info.slimMode { + return + } + redisHost := daprDefaultHost zipkinHost := daprDefaultHost - if dockerNetwork != "" { + if info.dockerNetwork != "" { // Default to network scoped alias of the container names when a dockerNetwork is specified. redisHost = DaprRedisContainerName zipkinHost = DaprZipkinContainerName @@ -524,9 +605,13 @@ func createComponentsAndConfiguration(wg *sync.WaitGroup, errorChan chan<- error } } -func createSlimConfiguration(wg *sync.WaitGroup, errorChan chan<- error, _ string, _ string) { +func createSlimConfiguration(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() + if !info.slimMode { + return + } + // For --slim we pass empty string so that we do not configure zipkin. err := createDefaultConfiguration("", DefaultConfigFilePath()) if err != nil { @@ -573,17 +658,9 @@ func sanitizeExtractPath(destination string, filePath string) (string, error) { func extractFile(filepath, dir, binaryFilePrefix string) (string, error) { var extractFunc func(string, string, string) (string, error) if archiveExt() == "zip" { - if !isEmbedded { - extractFunc = unzipExternalFile - } else { - extractFunc = unzipEmbeddedFile - } + extractFunc = unzipExternalFile } else { - if !isEmbedded { - extractFunc = untarExternalFile - } else { - extractFunc = untarEmbeddedFile - } + extractFunc = untarExternalFile } extractedFilePath, err := extractFunc(filepath, dir, binaryFilePrefix) @@ -591,49 +668,9 @@ func extractFile(filepath, dir, binaryFilePrefix string) (string, error) { return "", fmt.Errorf("error extracting %s binary: %s", binaryFilePrefix, err) } - if !isEmbedded { - err = os.Remove(filepath) - if err != nil { - return "", fmt.Errorf("failed to remove archive: %s", err) - } - } - return extractedFilePath, nil } -func unzipEmbeddedFile(filepath, dir, binaryFilePrefix string) (string, error) { - file := binaryStagePath(binaryFilePrefix) - f, err := binaries.Open(file) - if err != nil { - return "", fmt.Errorf("error open embedded file %s: %s", file, err) - } - defer f.Close() - - var fi fs.FileInfo - fi, err = f.Stat() - if err != nil { - return "", fmt.Errorf("error stat embedded file %s: %s", file, err) - } - - var fileBytes []byte - fileBytes, err = io.ReadAll(f) - if err != nil { - return "", fmt.Errorf("error read embedded file %s: %s", file, err) - } - - var reader *zip.Reader - reader, err = zip.NewReader(bytes.NewReader(fileBytes), fi.Size()) - if err != nil { - return "", fmt.Errorf("error open embedded zip file %s: %s", file, err) - } - - return unzip(reader, dir, binaryFilePrefix) -} - -func binaryStagePath(binaryFilePrefix string) string { - return path.Join("staging", defaultDaprBinDirName, binaryName(binaryFilePrefix)) -} - func unzipExternalFile(filepath, dir, binaryFilePrefix string) (string, error) { r, err := zip.OpenReader(filepath) if err != nil { @@ -688,17 +725,6 @@ func unzip(r *zip.Reader, targetDir string, binaryFilePrefix string) (string, er return foundBinary, nil } -func untarEmbeddedFile(filepath, dir, binaryFilePrefix string) (string, error) { - file := binaryStagePath(binaryFilePrefix) - reader, err := binaries.Open(file) - if err != nil { - return "", fmt.Errorf("error open embedded file %s: %s", file, err) - } - defer reader.Close() - - return untar(reader, dir, binaryFilePrefix) -} - func untarExternalFile(filepath, dir, binaryFilePrefix string) (string, error) { reader, err := os.Open(filepath) if err != nil { @@ -908,3 +934,93 @@ func checkAndOverWriteFile(filePath string, b []byte) error { } return nil } + +func prepareDaprInstallDir(daprBinDir string) error { + err := os.MkdirAll(daprBinDir, 0o777) + if err != nil { + return err + } + + err = os.Chmod(daprBinDir, 0o777) + if err != nil { + return err + } + + return nil +} + +func archiveExt() string { + ext := "tar.gz" + if runtime.GOOS == daprWindowsOS { + ext = "zip" + } + + return ext +} + +func downloadBinary(dir, version, binaryFilePrefix, githubRepo string) (string, error) { + fileURL := fmt.Sprintf( + "https://github.com/%s/%s/releases/download/v%s/%s", + cli_ver.DaprGitHubOrg, + githubRepo, + version, + binaryName(binaryFilePrefix)) + + return downloadFile(dir, fileURL) +} + +func binaryName(binaryFilePrefix string) string { + return fmt.Sprintf("%s_%s_%s.%s", binaryFilePrefix, runtime.GOOS, runtime.GOARCH, archiveExt()) +} + +// nolint:gosec +func downloadFile(dir string, url string) (string, error) { + tokens := strings.Split(url, "/") + fileName := tokens[len(tokens)-1] + + filepath := path.Join(dir, fileName) + _, err := os.Stat(filepath) + if os.IsExist(err) { + return "", nil + } + + resp, err := http.Get(url) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode == 404 { + return "", fmt.Errorf("version not found from url: %s", url) + } else if resp.StatusCode != 200 { + return "", fmt.Errorf("download failed with %d", resp.StatusCode) + } + + out, err := os.Create(filepath) + if err != nil { + return "", err + } + defer out.Close() + + _, err = io.Copy(out, resp.Body) + if err != nil { + return "", err + } + + return filepath, nil +} + +func parseVersionFile(fromDir string) (string, string) { + bytes, err := ioutil.ReadFile(path_filepath.Join(fromDir, "version.json")) + if err != nil { + return "", "" + } + + var versions map[string]string + err = json.Unmarshal(bytes, &versions) + if err != nil { + return "", "" + } + + return versions[daprRuntimeFilePrefix], versions[dashboardFilePrefix] +} From f465610b19fdc27dd572b8f88b27af7e483d082b Mon Sep 17 00:00:00 2001 From: "beiwei.ly" Date: Thu, 24 Feb 2022 16:07:29 +0800 Subject: [PATCH 14/24] fix default value for from-dir Signed-off-by: beiwei.ly --- cmd/init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/init.go b/cmd/init.go index 83473cc35..2b3748f76 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -131,7 +131,7 @@ func init() { InitCmd.Flags().BoolVarP(&enableMTLS, "enable-mtls", "", true, "Enable mTLS in your cluster") InitCmd.Flags().BoolVarP(&enableHA, "enable-ha", "", false, "Enable high availability (HA) mode") InitCmd.Flags().String("network", "", "The Docker network on which to deploy the Dapr runtime") - InitCmd.Flags().StringVarP(&fromDir, "from-dir", "", "artifacts", "Use Dapr artifacts from local directory instead of from network to init") + InitCmd.Flags().StringVarP(&fromDir, "from-dir", "", "", "Use Dapr artifacts from local directory instead of from network to init") InitCmd.Flags().BoolP("help", "h", false, "Print this help message") InitCmd.Flags().StringArrayVar(&values, "set", []string{}, "set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)") InitCmd.Flags().String("image-repository", "", "Custom/Private docker image repository url") From c59dc67cd0ab9d5971e7e7d70f2387344e6c7188 Mon Sep 17 00:00:00 2001 From: "beiwei.ly" Date: Thu, 24 Feb 2022 16:15:45 +0800 Subject: [PATCH 15/24] fix lint issue Signed-off-by: beiwei.ly --- pkg/standalone/standalone.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 241678b71..c8a3fe3b2 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -167,7 +167,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod var wg sync.WaitGroup errorChan := make(chan error) - var initSteps = []func(*sync.WaitGroup, chan<- error, initInfo){ + initSteps := []func(*sync.WaitGroup, chan<- error, initInfo){ createSlimConfiguration, createComponentsAndConfiguration, installDaprRuntime, @@ -625,19 +625,19 @@ func makeDefaultComponentsDir() error { componentsDir := DefaultComponentsDirPath() _, err := os.Stat(componentsDir) if os.IsNotExist(err) { - errDir := os.MkdirAll(componentsDir, 0755) + errDir := os.MkdirAll(componentsDir, 0o755) if errDir != nil { return fmt.Errorf("error creating default components folder: %s", errDir) } } - os.Chmod(componentsDir, 0777) + os.Chmod(componentsDir, 0o777) return nil } func makeExecutable(filepath string) error { if runtime.GOOS != daprWindowsOS { - err := os.Chmod(filepath, 0777) + err := os.Chmod(filepath, 0o777) if err != nil { return err } @@ -807,7 +807,7 @@ func moveFileToPath(filepath string, installLocation string) (string, error) { } // #nosec G306 - if err = ioutil.WriteFile(destFilePath, input, 0644); err != nil { + if err = ioutil.WriteFile(destFilePath, input, 0o644); err != nil { if runtime.GOOS != daprWindowsOS && strings.Contains(err.Error(), "permission denied") { err = errors.New(err.Error() + " - please run with sudo") } @@ -928,7 +928,7 @@ func checkAndOverWriteFile(filePath string, b []byte) error { _, err := os.Stat(filePath) if os.IsNotExist(err) { // #nosec G306 - if err = ioutil.WriteFile(filePath, b, 0644); err != nil { + if err = ioutil.WriteFile(filePath, b, 0o644); err != nil { return err } } From 12836a0b60d01180340164a3009c4461301d9b3a Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Thu, 24 Feb 2022 16:19:18 +0800 Subject: [PATCH 16/24] add license header Signed-off-by: Ian Luo --- .github/scripts/archive_dapr_artifacts.sh | 2 +- pkg/standalone/docker.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/scripts/archive_dapr_artifacts.sh b/.github/scripts/archive_dapr_artifacts.sh index 269015ad0..6d0a2cff6 100755 --- a/.github/scripts/archive_dapr_artifacts.sh +++ b/.github/scripts/archive_dapr_artifacts.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # ------------------------------------------------------------ -# Copyright 2021 The Dapr Authors +# Copyright 2022 The Dapr Authors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file_base except in compliance with the License. # You may obtain a copy of the License at diff --git a/pkg/standalone/docker.go b/pkg/standalone/docker.go index 13b888e18..93c91511e 100644 --- a/pkg/standalone/docker.go +++ b/pkg/standalone/docker.go @@ -1,3 +1,16 @@ +/* +Copyright 2022 The Dapr Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package standalone import ( From 7df191fb58821b8edcf682262f8d51e5bc8e60d3 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Thu, 24 Feb 2022 16:36:01 +0800 Subject: [PATCH 17/24] fix script running issue in gh workflow Signed-off-by: Ian Luo --- .github/workflows/dapr_cli.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index 83184e575..40d6a1627 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -90,8 +90,10 @@ jobs: make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - name: Run archive_dapr_artifacts.sh to archive Dapr artificats if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' + shell: bash run: | - sh ./.github/scripts/archive_dapr_artifacts.sh -o dapr_artifacts + chmod +x ./.github/scripts/archive_dapr_artifacts.sh + ./.github/scripts/archive_dapr_artifacts.sh -o dapr_artifacts tar czf ${{ env.ARCHIVE_OUTDIR }}/dapr_artifacts.tar.gz -C dapr_artifacts dist docker - name: Create release_version.txt if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' From f806f038bb7420450c670596540cd94ccff78848 Mon Sep 17 00:00:00 2001 From: "beiwei.ly" Date: Tue, 8 Mar 2022 11:13:43 +0800 Subject: [PATCH 18/24] remove archive_dapr_artifacts.sh from github workflow Signed-off-by: beiwei.ly --- .github/scripts/archive_dapr_artifacts.sh | 167 ---------------------- .github/workflows/dapr_cli.yaml | 7 - 2 files changed, 174 deletions(-) delete mode 100755 .github/scripts/archive_dapr_artifacts.sh diff --git a/.github/scripts/archive_dapr_artifacts.sh b/.github/scripts/archive_dapr_artifacts.sh deleted file mode 100755 index 6d0a2cff6..000000000 --- a/.github/scripts/archive_dapr_artifacts.sh +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env bash - -# ------------------------------------------------------------ -# Copyright 2022 The Dapr Authors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file_base except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ------------------------------------------------------------ - -# Http request CLI -DAPR_HTTP_REQUEST_CLI=curl - -# GitHub Organization and repo name to download release -GITHUB_ORG=dapr -GITHUB_DAPR_REPO=dapr -GITHUB_DASHBOARD_REPO=dashboard - -# Dapr binaries filename -DAPRD_FILENAME=daprd -PLACEMENT_FILENAME=placement -DASHBOARD_FILENAME=dashboard - -checkHttpRequestCLI() { - if type "curl" > /dev/null; then - DAPR_HTTP_REQUEST_CLI=curl - elif type "wget" > /dev/null; then - DAPR_HTTP_REQUEST_CLI=wget - else - echo "Either curl or wget is required" - exit 1 - fi -} - -getLatestRelease() { - local daprReleaseUrl="https://api.github.com/repos/${GITHUB_ORG}/$1/releases" - local latest_release="" - - if [ "$DAPR_HTTP_REQUEST_CLI" == "curl" ]; then - latest_release=$(curl -s $daprReleaseUrl | grep \"tag_name\" | grep -v rc | awk 'NR==1{print $2}' | sed -n 's/\"\(.*\)\",/\1/p') - else - latest_release=$(wget -q --header="Accept: application/json" -O - $daprReleaseUrl | grep \"tag_name\" | grep -v rc | awk 'NR==1{print $2}' | sed -n 's/\"\(.*\)\",/\1/p') - fi - - echo $latest_release -} - -downloadFile() { - local repo=$1 - local file_base=$2 - local ver=$3 - local platform=$4 - local ext="tar.gz" - local out_dir=${TARGET_DIR}/dist - - if [[ "${platform}" == "windows_amd64" ]]; then - ext="zip" - fi - - local filename=${file_base}_${platform}.${ext} - local download_url="https://github.com/${GITHUB_ORG}/${repo}/releases/download/${ver}/${filename}" - - mkdir -p ${out_dir} - - echo "Downloading $download_url to ${out_dir}/${filename}..." - if [ "$DAPR_HTTP_REQUEST_CLI" == "curl" ]; then - curl -SsL "$download_url" -o "${out_dir}/${filename}" - else - wget -q -O "${out_dir}/${filename}" "$download_url" - fi - - if [ ! -f "${out_dir}/${filename}" ]; then - echo "failed to download $download_url ..." - exit 1 - fi -} - -downloadDockerImage() { - local image_name=$1 - local image_ver=$2 - local docker_image="${image_name}:${image_ver}" - if [[ ${image_ver} == "latest" ]]; then - docker_image=${image_name} - fi - local file_name=$(echo ${docker_image} | sed -e 's/\//-/g' | sed -e 's/:/-/g').tar.gz - local out_dir=${TARGET_DIR}/docker - - mkdir -p ${out_dir} - - echo "Pulling docker image ${docker_image}..." - docker pull "${docker_image}" - echo "Saving docker image to ${out_dir}/${file_name}..." - docker save -o "${out_dir}/${file_name}" "${docker_image}" -} - -downloadArtifacts() { - for platform in "darwin_amd64" "darwin_arm64" "linux_amd64" "linux_arm64" "windows_amd64"; do - downloadFile ${GITHUB_DAPR_REPO} ${DAPRD_FILENAME} ${RUNTIME_VER} ${platform} - downloadFile ${GITHUB_DAPR_REPO} ${PLACEMENT_FILENAME} ${RUNTIME_VER} ${platform} - downloadFile ${GITHUB_DASHBOARD_REPO} ${DASHBOARD_FILENAME} ${DASHBOARD_VER} ${platform} - done -} - -downloadDockerImages() { - downloadDockerImage "daprio/dapr" $(echo ${RUNTIME_VER} | sed -e 's/^v//') - downloadDockerImage "openzipkin/zipkin" "latest" - downloadDockerImage "redis" "latest" -} - -writeVersion() { - local runtime_ver=$(echo ${RUNTIME_VER} | sed -e 's/^v//') - local dashboard_ver=$(echo ${DASHBOARD_VER} | sed -e 's/^v//') - cat < ${TARGET_DIR}/version.json -{ - "daprd": "${runtime_ver}", - "dashboard": "${dashboard_ver}" -} -VERSION -} - -fail_trap() { - result=$? - if [ "$result" != "0" ]; then - echo "Failed to download Dapr artifacts" - echo "For support, go to https://dapr.io" - fi - exit $result -} - -# ----------------------------------------------------------------------------- -# main -# ----------------------------------------------------------------------------- -trap "fail_trap" EXIT - -while getopts 'r:d:o:' options; do - case ${options} in - r) RUNTIME_VER=${OPTARG};; - d) DASHBOARD_VER=${OPTARG};; - o) TARGET_DIR=${OPTARG};; - esac -done - -checkHttpRequestCLI - -if [[ -z ${RUNTIME_VER} ]]; then - RUNTIME_VER=$(getLatestRelease ${GITHUB_DAPR_REPO}) -fi - -if [[ -z ${DASHBOARD_VER} ]]; then - DASHBOARD_VER=$(getLatestRelease ${GITHUB_DASHBOARD_REPO}) -fi - -if [[ -z ${TARGET_DIR} ]]; then - TARGET_DIR=artifacts -fi - -mkdir -p ${TARGET_DIR} -writeVersion -downloadArtifacts -downloadDockerImages - - diff --git a/.github/workflows/dapr_cli.yaml b/.github/workflows/dapr_cli.yaml index e01a0b989..0c59e88ef 100644 --- a/.github/workflows/dapr_cli.yaml +++ b/.github/workflows/dapr_cli.yaml @@ -88,13 +88,6 @@ jobs: run: | mkdir -p ${{ env.ARCHIVE_OUTDIR }} make release GOOS=${{ matrix.target_os }} GOARCH=${{ matrix.target_arch }} ARCHIVE_OUT_DIR=${{ env.ARCHIVE_OUTDIR }} - - name: Run archive_dapr_artifacts.sh to archive Dapr artificats - if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' - shell: bash - run: | - chmod +x ./.github/scripts/archive_dapr_artifacts.sh - ./.github/scripts/archive_dapr_artifacts.sh -o dapr_artifacts - tar czf ${{ env.ARCHIVE_OUTDIR }}/dapr_artifacts.tar.gz -C dapr_artifacts dist docker - name: Create release_version.txt if: matrix.target_arch == 'amd64' && matrix.target_os == 'linux' run: | From 914df7f3954ed6d6f979faaf3f707d42ed851460 Mon Sep 17 00:00:00 2001 From: "beiwei.ly" Date: Wed, 9 Mar 2022 10:45:40 +0800 Subject: [PATCH 19/24] bypass loading zipkin and redis from local dir Signed-off-by: beiwei.ly --- pkg/standalone/standalone.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 59f9af8e6..1dc30f1ba 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -275,8 +275,7 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { dir := path_filepath.Join(info.fromDir, dockerImageSubDir) err = loadDocker(dir, imageName) if err != nil { - errorChan <- err - return + print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s, ignore.", imageName, dir) } } @@ -343,8 +342,7 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { dir := path_filepath.Join(info.fromDir, dockerImageSubDir) err = loadDocker(dir, imageName) if err != nil { - errorChan <- err - return + print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s, ignore.", imageName, dir) } } From 406d3cb39e8292a57efd97ba5aa1546af2c58caa Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Wed, 9 Mar 2022 10:50:56 +0800 Subject: [PATCH 20/24] fix lint issue Signed-off-by: Ian Luo --- pkg/standalone/docker.go | 6 +++--- pkg/standalone/standalone.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/standalone/docker.go b/pkg/standalone/docker.go index 810f1f51b..301ebde7f 100644 --- a/pkg/standalone/docker.go +++ b/pkg/standalone/docker.go @@ -70,7 +70,7 @@ func loadDocker(dir string, dockerImage string) error { // check if the container either exists and stopped or is running. func confirmContainerIsRunningOrExists(containerName string, isRunning bool) (bool, error) { - // e.g. docker ps --filter name=dapr_redis --filter status=running --format {{.Names}} + // e.g. docker ps --filter name=dapr_redis --filter status=running --format {{.Names}}. args := []string{"ps", "--all", "--filter", "name=" + containerName} @@ -82,12 +82,12 @@ func confirmContainerIsRunningOrExists(containerName string, isRunning bool) (bo response, err := utils.RunCmdAndWait("docker", args...) response = strings.TrimSuffix(response, "\n") - // If 'docker ps' failed due to some reason + // If 'docker ps' failed due to some reason. if err != nil { //nolint return false, fmt.Errorf("unable to confirm whether %s is running or exists. error\n%v", containerName, err.Error()) } - // 'docker ps' worked fine, but the response did not have the container name + // 'docker ps' worked fine, but the response did not have the container name. if response == "" || response != containerName { if isRunning { return false, fmt.Errorf("container %s is not running", containerName) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 1dc30f1ba..ee5c9cf07 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -664,7 +664,7 @@ func extractFile(filepath, dir, binaryFilePrefix string) (string, error) { extractedFilePath, err := extractFunc(filepath, dir, binaryFilePrefix) if err != nil { - return "", fmt.Errorf("error extracting %s binary: %s", binaryFilePrefix, err) + return "", fmt.Errorf("error extracting %s binary: %w", binaryFilePrefix, err) } return extractedFilePath, nil @@ -673,7 +673,7 @@ func extractFile(filepath, dir, binaryFilePrefix string) (string, error) { func unzipExternalFile(filepath, dir, binaryFilePrefix string) (string, error) { r, err := zip.OpenReader(filepath) if err != nil { - return "", fmt.Errorf("error open zip file %s: %s", filepath, err) + return "", fmt.Errorf("error open zip file %s: %w", filepath, err) } defer r.Close() From 40bb06fa1438b848b0f704a89078fd04ccb4c520 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Wed, 9 Mar 2022 16:14:17 +0800 Subject: [PATCH 21/24] enhance warning message Signed-off-by: Ian Luo --- pkg/standalone/standalone.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index ee5c9cf07..09e27c5a5 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -275,7 +275,7 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { dir := path_filepath.Join(info.fromDir, dockerImageSubDir) err = loadDocker(dir, imageName) if err != nil { - print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s, ignore.", imageName, dir) + print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s directory, ignore.", imageName, dir) } } @@ -342,7 +342,7 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { dir := path_filepath.Join(info.fromDir, dockerImageSubDir) err = loadDocker(dir, imageName) if err != nil { - print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s, ignore.", imageName, dir) + print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s directory, ignore.", imageName, dir) } } From c7129753404af45c789a9eaa91079afbe56d2dec Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Mon, 14 Mar 2022 14:10:17 +0800 Subject: [PATCH 22/24] bypass zipkin/redis in local dir mode Signed-off-by: Ian Luo --- pkg/standalone/standalone.go | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 09e27c5a5..bc830a240 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -249,7 +249,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() - if info.slimMode { + if info.slimMode || info.fromDir != "" { return } @@ -271,14 +271,6 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { imageName = fmt.Sprintf("%s/%s", info.imageRepositoryURL, imageName) } - if info.fromDir != "" { - dir := path_filepath.Join(info.fromDir, dockerImageSubDir) - err = loadDocker(dir, imageName) - if err != nil { - print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s directory, ignore.", imageName, dir) - } - } - args = append(args, "run", "--name", zipkinContainerName, @@ -316,7 +308,7 @@ func runZipkin(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { func runRedis(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { defer wg.Done() - if info.slimMode { + if info.slimMode || info.fromDir != "" { return } @@ -338,14 +330,6 @@ func runRedis(wg *sync.WaitGroup, errorChan chan<- error, info initInfo) { imageName = fmt.Sprintf("%s/%s", info.imageRepositoryURL, imageName) } - if info.fromDir != "" { - dir := path_filepath.Join(info.fromDir, dockerImageSubDir) - err = loadDocker(dir, imageName) - if err != nil { - print.WarningStatusEvent(os.Stdout, "Docker image %s not available in %s directory, ignore.", imageName, dir) - } - } - args = append(args, "run", "--name", redisContainerName, From cf4c310cc677a3c32455f3f18bc0e864c92243a0 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Mar 2022 13:22:53 +0800 Subject: [PATCH 23/24] skip container running check in local installation mode Signed-off-by: Ian Luo --- pkg/standalone/standalone.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index bc830a240..47224cb19 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -231,6 +231,10 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod print.InfoStatusEvent(os.Stdout, "%s binary has been installed to %s.", placementServiceFilePrefix, daprBinDir) } else { dockerContainerNames := []string{DaprPlacementContainerName, DaprRedisContainerName, DaprZipkinContainerName} + // Skip redis and zipkin in local installation mode + if fromDir != "" { + dockerContainerNames = []string{DaprPlacementContainerName} + } for _, container := range dockerContainerNames { containerName := utils.CreateContainerName(container, dockerNetwork) ok, err := confirmContainerIsRunningOrExists(containerName, true) From 887505714014f982f479a132b54def45c66ed545 Mon Sep 17 00:00:00 2001 From: Ian Luo Date: Fri, 18 Mar 2022 13:33:00 +0800 Subject: [PATCH 24/24] fix lint issue Signed-off-by: Ian Luo --- pkg/standalone/standalone.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/standalone/standalone.go b/pkg/standalone/standalone.go index 47224cb19..ff6b1aa8e 100644 --- a/pkg/standalone/standalone.go +++ b/pkg/standalone/standalone.go @@ -231,7 +231,7 @@ func Init(runtimeVersion, dashboardVersion string, dockerNetwork string, slimMod print.InfoStatusEvent(os.Stdout, "%s binary has been installed to %s.", placementServiceFilePrefix, daprBinDir) } else { dockerContainerNames := []string{DaprPlacementContainerName, DaprRedisContainerName, DaprZipkinContainerName} - // Skip redis and zipkin in local installation mode + // Skip redis and zipkin in local installation mode. if fromDir != "" { dockerContainerNames = []string{DaprPlacementContainerName} }