feat: .env file support — skip prompts on repeat deploys
- /opt/fw/.env stores token, cloud, node, port, upstream - If .env exists with WALLARM_TOKEN, all prompts are skipped - Saved automatically after successful deployment - Perfect for testing: edit .env once, deploy repeatedly
This commit is contained in:
parent
cbe6d51ac6
commit
e9dff30d84
1 changed files with 130 additions and 76 deletions
|
|
@ -37,94 +37,128 @@ func runDeployFlow(r preflight.Result) {
|
||||||
var s state.State
|
var s state.State
|
||||||
s.DeploymentType = "native"
|
s.DeploymentType = "native"
|
||||||
|
|
||||||
// Step 1: Cloud region
|
// Check for .env file — skip prompts if present
|
||||||
fmt.Println()
|
envPath := "/opt/fw/.env"
|
||||||
fmt.Println("─── Cloud Region ───")
|
envData, _ := os.ReadFile(envPath)
|
||||||
if r.USReachable && r.EUReachable {
|
envMap := parseEnv(string(envData))
|
||||||
fmt.Println(" [1] US (us1.api.wallarm.com)")
|
skipPrompts := envMap["WALLARM_TOKEN"] != ""
|
||||||
fmt.Println(" [2] EU (api.wallarm.com)")
|
|
||||||
fmt.Print("Choose region [1/2]: ")
|
if skipPrompts {
|
||||||
choice, _ := reader.ReadString('\n')
|
fmt.Println()
|
||||||
choice = strings.TrimSpace(choice)
|
fmt.Println("Using saved configuration from /opt/fw/.env")
|
||||||
if choice == "2" {
|
s.CloudRegion = envMap["WALLARM_CLOUD"]
|
||||||
s.CloudRegion = "EU"
|
if s.CloudRegion == "US" {
|
||||||
s.APIHost = "api.wallarm.com"
|
s.APIHost = "us1.api.wallarm.com"
|
||||||
} else {
|
} 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.CloudRegion = "US"
|
||||||
s.APIHost = "us1.api.wallarm.com"
|
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
|
// Step 2: API Token
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Print("Wallarm API Token (Deploy role): ")
|
fmt.Print("Wallarm API Token (Deploy role): ")
|
||||||
token, _ := reader.ReadString('\n')
|
token, _ := reader.ReadString('\n')
|
||||||
s.APIToken = strings.TrimSpace(token)
|
s.APIToken = strings.TrimSpace(token)
|
||||||
if s.APIToken == "" {
|
if s.APIToken == "" {
|
||||||
fmt.Println("Token cannot be empty.")
|
fmt.Println("Token cannot be empty.")
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Node configuration
|
// Step 3: Node configuration
|
||||||
fmt.Println()
|
var nodeName, port, upstreamIP, upstreamPort, labels string
|
||||||
fmt.Print("Node name: ")
|
if skipPrompts {
|
||||||
nodeName, _ := reader.ReadString('\n')
|
nodeName = envMap["WALLARM_NODE"]
|
||||||
nodeName = strings.TrimSpace(nodeName)
|
port = envMap["WALLARM_PORT"]
|
||||||
if nodeName == "" {
|
upstreamIP = envMap["WALLARM_UPSTREAM_IP"]
|
||||||
fmt.Println("Node name required.")
|
upstreamPort = envMap["WALLARM_UPSTREAM_PORT"]
|
||||||
return
|
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]: ")
|
if port == "" { port = "8081" }
|
||||||
port, _ := reader.ReadString('\n')
|
if upstreamIP == "" { upstreamIP = "127.0.0.1" }
|
||||||
port = strings.TrimSpace(port)
|
if upstreamPort == "" { upstreamPort = "80" }
|
||||||
if port == "" {
|
if labels == "" { labels = "group=" + nodeName }
|
||||||
port = "8081"
|
|
||||||
}
|
|
||||||
address := "0.0.0.0:" + port
|
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"
|
baseDir := "/opt/fw"
|
||||||
instanceDir := baseDir + "/" + nodeName + "/wallarm"
|
instanceDir := baseDir + "/" + nodeName + "/wallarm"
|
||||||
|
|
||||||
|
|
@ -178,6 +212,11 @@ WALLARM_REGION=%s
|
||||||
fmt.Fprintf(os.Stderr, "Warning: could not save state: %v\n", err)
|
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()
|
||||||
fmt.Println("✅ Deployment complete!")
|
fmt.Println("✅ Deployment complete!")
|
||||||
fmt.Println()
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue