diff --git a/cmd/deploy/main.go b/cmd/deploy/main.go index 47db651..284b2cf 100644 --- a/cmd/deploy/main.go +++ b/cmd/deploy/main.go @@ -37,94 +37,128 @@ func runDeployFlow(r preflight.Result) { var s state.State s.DeploymentType = "native" - // Step 1: Cloud region - fmt.Println() - fmt.Println("─── Cloud Region ───") - if r.USReachable && r.EUReachable { - fmt.Println(" [1] US (us1.api.wallarm.com)") - fmt.Println(" [2] EU (api.wallarm.com)") - fmt.Print("Choose region [1/2]: ") - choice, _ := reader.ReadString('\n') - choice = strings.TrimSpace(choice) - if choice == "2" { - s.CloudRegion = "EU" - s.APIHost = "api.wallarm.com" + // Check for .env file — skip prompts if present + envPath := "/opt/fw/.env" + envData, _ := os.ReadFile(envPath) + envMap := parseEnv(string(envData)) + skipPrompts := envMap["WALLARM_TOKEN"] != "" + + if skipPrompts { + fmt.Println() + fmt.Println("Using saved configuration from /opt/fw/.env") + s.CloudRegion = envMap["WALLARM_CLOUD"] + if s.CloudRegion == "US" { + s.APIHost = "us1.api.wallarm.com" } else { + s.APIHost = "api.wallarm.com" + } + s.APIToken = envMap["WALLARM_TOKEN"] + } else { + // Step 1: Cloud region + fmt.Println() + fmt.Println("─── Cloud Region ───") + if r.USReachable && r.EUReachable { + fmt.Println(" [1] US (us1.api.wallarm.com)") + fmt.Println(" [2] EU (api.wallarm.com)") + fmt.Print("Choose region [1/2]: ") + choice, _ := reader.ReadString('\n') + choice = strings.TrimSpace(choice) + if choice == "2" { + s.CloudRegion = "EU" + s.APIHost = "api.wallarm.com" + } else { + s.CloudRegion = "US" + s.APIHost = "us1.api.wallarm.com" + } + } else if r.USReachable { + fmt.Println(" US (us1.api.wallarm.com) — only reachable region") s.CloudRegion = "US" s.APIHost = "us1.api.wallarm.com" + } else { + fmt.Println(" EU (api.wallarm.com) — only reachable region") + s.CloudRegion = "EU" + s.APIHost = "api.wallarm.com" } - } else if r.USReachable { - fmt.Println(" US (us1.api.wallarm.com) — only reachable region") - s.CloudRegion = "US" - s.APIHost = "us1.api.wallarm.com" - } else { - fmt.Println(" EU (api.wallarm.com) — only reachable region") - s.CloudRegion = "EU" - s.APIHost = "api.wallarm.com" - } - // Step 2: API Token - fmt.Println() - fmt.Print("Wallarm API Token (Deploy role): ") - token, _ := reader.ReadString('\n') - s.APIToken = strings.TrimSpace(token) - if s.APIToken == "" { - fmt.Println("Token cannot be empty.") - return + // Step 2: API Token + fmt.Println() + fmt.Print("Wallarm API Token (Deploy role): ") + token, _ := reader.ReadString('\n') + s.APIToken = strings.TrimSpace(token) + if s.APIToken == "" { + fmt.Println("Token cannot be empty.") + return + } } // Step 3: Node configuration - fmt.Println() - fmt.Print("Node name: ") - nodeName, _ := reader.ReadString('\n') - nodeName = strings.TrimSpace(nodeName) - if nodeName == "" { - fmt.Println("Node name required.") - return + var nodeName, port, upstreamIP, upstreamPort, labels string + if skipPrompts { + nodeName = envMap["WALLARM_NODE"] + port = envMap["WALLARM_PORT"] + upstreamIP = envMap["WALLARM_UPSTREAM_IP"] + upstreamPort = envMap["WALLARM_UPSTREAM_PORT"] + labels = envMap["WALLARM_LABELS"] + fmt.Printf("\n Node: %s | Port: %s | Upstream: %s:%s | Cloud: %s\n", + nodeName, port, upstreamIP, upstreamPort, s.CloudRegion) + } else { + fmt.Println() + fmt.Print("Node name: ") + nodeName, _ = reader.ReadString('\n') + nodeName = strings.TrimSpace(nodeName) + if nodeName == "" { + fmt.Println("Node name required.") + return + } + + fmt.Print("Listen port [8081]: ") + port, _ = reader.ReadString('\n') + port = strings.TrimSpace(port) + if port == "" { + port = "8081" + } + + fmt.Print("Upstream IP [127.0.0.1]: ") + upstreamIP, _ = reader.ReadString('\n') + upstreamIP = strings.TrimSpace(upstreamIP) + if upstreamIP == "" { + upstreamIP = "127.0.0.1" + } + + fmt.Print("Upstream port [80]: ") + upstreamPort, _ = reader.ReadString('\n') + upstreamPort = strings.TrimSpace(upstreamPort) + if upstreamPort == "" { + upstreamPort = "80" + } + + fmt.Print("Labels [group=" + nodeName + "]: ") + labels, _ = reader.ReadString('\n') + labels = strings.TrimSpace(labels) + if labels == "" { + labels = "group=" + nodeName + } + + fmt.Println() + fmt.Printf(" Node: %s\n", nodeName) + fmt.Printf(" Listen: %s\n", "0.0.0.0:"+port) + fmt.Printf(" Upstream: %s:%s\n", upstreamIP, upstreamPort) + fmt.Printf(" Region: %s (%s)\n", s.CloudRegion, s.APIHost) + fmt.Print("\nProceed with deployment? [Y/n]: ") + confirm, _ := reader.ReadString('\n') + confirm = strings.TrimSpace(strings.ToLower(confirm)) + if confirm != "" && confirm != "y" && confirm != "yes" { + fmt.Println("Cancelled.") + return + } } - fmt.Print("Listen port [8081]: ") - port, _ := reader.ReadString('\n') - port = strings.TrimSpace(port) - if port == "" { - port = "8081" - } + if port == "" { port = "8081" } + if upstreamIP == "" { upstreamIP = "127.0.0.1" } + if upstreamPort == "" { upstreamPort = "80" } + if labels == "" { labels = "group=" + nodeName } address := "0.0.0.0:" + port - fmt.Print("Upstream IP [127.0.0.1]: ") - upstreamIP, _ := reader.ReadString('\n') - upstreamIP = strings.TrimSpace(upstreamIP) - if upstreamIP == "" { - upstreamIP = "127.0.0.1" - } - - fmt.Print("Upstream port [80]: ") - upstreamPort, _ := reader.ReadString('\n') - upstreamPort = strings.TrimSpace(upstreamPort) - if upstreamPort == "" { - upstreamPort = "80" - } - - fmt.Print("Labels [group=" + nodeName + "]: ") - labels, _ := reader.ReadString('\n') - labels = strings.TrimSpace(labels) - if labels == "" { - labels = "group=" + nodeName - } - - fmt.Println() - fmt.Printf(" Node: %s\n", nodeName) - fmt.Printf(" Listen: %s\n", address) - fmt.Printf(" Upstream: %s:%s\n", upstreamIP, upstreamPort) - fmt.Printf(" Region: %s (%s)\n", s.CloudRegion, s.APIHost) - fmt.Print("\nProceed with deployment? [Y/n]: ") - confirm, _ := reader.ReadString('\n') - confirm = strings.TrimSpace(strings.ToLower(confirm)) - if confirm != "" && confirm != "y" && confirm != "yes" { - fmt.Println("Cancelled.") - return - } - baseDir := "/opt/fw" instanceDir := baseDir + "/" + nodeName + "/wallarm" @@ -178,6 +212,11 @@ WALLARM_REGION=%s fmt.Fprintf(os.Stderr, "Warning: could not save state: %v\n", err) } + // Save .env for future runs + os.WriteFile(envPath, []byte(fmt.Sprintf( + "WALLARM_TOKEN=%s\nWALLARM_CLOUD=%s\nWALLARM_NODE=%s\nWALLARM_PORT=%s\nWALLARM_UPSTREAM_IP=%s\nWALLARM_UPSTREAM_PORT=%s\nWALLARM_LABELS=%s\n", + s.APIToken, s.CloudRegion, nodeName, port, upstreamIP, upstreamPort, labels)), 0644) + fmt.Println() fmt.Println("✅ Deployment complete!") fmt.Println() @@ -334,3 +373,18 @@ deployment. On subsequent runs, it shows your existing deployments. } } } + +func parseEnv(data string) map[string]string { + m := map[string]string{} + for _, line := range strings.Split(data, "\n") { + line = strings.TrimSpace(line) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + parts := strings.SplitN(line, "=", 2) + if len(parts) == 2 { + m[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) + } + } + return m +}