Skip to content

Commit

Permalink
Merge pull request #516 from Chrisyhjiang/140
Browse files Browse the repository at this point in the history
Issue 140
  • Loading branch information
lionello authored Jul 4, 2024
2 parents 43c8ec6 + fef34f3 commit 54bf92a
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 5 deletions.
162 changes: 162 additions & 0 deletions src/cmd/cli/command/collectUnsetEnvVars_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package command

import (
"testing"

"github.com/compose-spec/compose-go/v2/types"
)

// Helper function to convert a string to a pointer to a string
func stringPtr(s string) *string {
return &s
}

// Helper function to check if two slices contain the same elements, regardless of order
func sameElements(a, b []string) bool {
if len(a) != len(b) {
return false
}
elemCount := make(map[string]int)
for _, elem := range a {
elemCount[elem]++
}
for _, elem := range b {
if elemCount[elem] == 0 {
return false
}
elemCount[elem]--
}
return true
}

// Test function for collectUnsetEnvVars
func TestCollectUnsetEnvVars(t *testing.T) {
tests := []struct {
name string
project *types.Project
expected []string
}{
{
name: "Nil project",
project: nil,
expected: []string{},
},
{
name: "No unset environment variables (map structure)",
project: &types.Project{
Services: map[string]types.ServiceConfig{
"service1": {
Name: "service1",
Environment: types.MappingWithEquals{
"ENV1": stringPtr("value1"),
"ENV2": stringPtr("value2"),
},
},
},
},
expected: []string{},
},
{
name: "Some unset environment variables (map structure)",
project: &types.Project{
Services: map[string]types.ServiceConfig{
"service1": {
Name: "service1",
Environment: types.MappingWithEquals{
"ENV1": stringPtr("value1"),
"ENV2": nil,
"ENV3": stringPtr(""),
},
},
},
},
expected: []string{"ENV2"},
},
{
name: "All unset environment variables (map structure)",
project: &types.Project{
Services: map[string]types.ServiceConfig{
"service1": {
Name: "service1",
Environment: types.MappingWithEquals{
"ENV1": nil,
"ENV2": nil,
},
},
},
},
expected: []string{"ENV1", "ENV2"},
},
{
name: "Some unset environment variables (array structure)",
project: &types.Project{
Services: map[string]types.ServiceConfig{
"service1": {
Name: "service1",
Environment: types.MappingWithEquals{
"ENV1": stringPtr("value1"),
"ENV2": nil,
},
},
},
},
expected: []string{"ENV2"},
},
{
name: "Multiple services with unset environment variables",
project: &types.Project{
Services: map[string]types.ServiceConfig{
"service1": {
Name: "service1",
Environment: types.MappingWithEquals{
"ENV1": stringPtr("value1"),
"ENV2": nil,
},
},
"service2": {
Name: "service2",
Environment: types.MappingWithEquals{
"ENV3": stringPtr(""),
"ENV4": stringPtr("value4"),
"ENV5": nil,
},
},
},
},
expected: []string{"ENV2", "ENV5"},
},
{
name: "Services with map and array structure",
project: &types.Project{
Services: map[string]types.ServiceConfig{
"x": {
Name: "x",
Environment: types.MappingWithEquals{
"regular": stringPtr("value"),
"empty": stringPtr(""),
"config": nil,
},
},
"y": {
Name: "y",
Environment: types.MappingWithEquals{
"REDIS_HOST": stringPtr("x"),
"EMPTY": stringPtr(""),
"CONFIG": nil,
},
},
},
},
expected: []string{"config", "CONFIG"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := collectUnsetEnvVars(tt.project)
if !sameElements(result, tt.expected) {
t.Errorf("collectUnsetEnvVars() = %v, want %v", result, tt.expected)
}
})
}
}
39 changes: 34 additions & 5 deletions src/cmd/cli/command/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math/rand"
"os"
"os/exec"
"path/filepath"
"regexp"
"slices"
"strings"
Expand All @@ -24,6 +25,7 @@ import (
"github.com/DefangLabs/defang/src/pkg/types"
"github.com/aws/smithy-go"
"github.com/bufbuild/connect-go"
proj "github.com/compose-spec/compose-go/v2/types"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -488,10 +490,9 @@ var generateCmd = &cobra.Command{
Prompt: &survey.Input{
Message: "Please describe the service you'd like to build:",
Help: `Here are some example prompts you can use:
"A simple 'hello world' function"
"A service with 2 endpoints, one to upload and the other to download a file from AWS S3"
"A service with a default endpoint that returns an HTML page with a form asking for the user's name and then a POST endpoint to handle the form post when the user clicks the 'submit' button\"
Generate will write files in the current folder. You can edit them and then deploy using 'defang compose up --tail' when ready.`,
"A simple 'hello world' function"
"A service with 2 endpoints, one to upload and the other to download a file from AWS S3"
"A service with a default endpoint that returns an HTML page with a form asking for the user's name and then a POST endpoint to handle the form post when the user clicks the 'submit' button"`,
},
Validate: survey.MinLength(5),
},
Expand Down Expand Up @@ -573,11 +574,39 @@ Generate will write files in the current folder. You can edit them and then depl
if prompt.Folder != "." {
cd = "`cd " + prompt.Folder + "` and "
}
printDefangHint("Check the files in your favorite editor.\nTo deploy the service, "+cd+"do:", "compose up")

// Load the project and check for empty environment variables
var envInstructions = ""
loader := compose.Loader{ComposeFilePath: filepath.Join(prompt.Folder, "compose.yaml")}
project, _ := loader.LoadCompose(cmd.Context())

envVars := collectUnsetEnvVars(project) // if err != nil -> proj == nil, which is handled in the collectUnsetEnvVars function
envInstructions = strings.Join(envVars, " ")

if envInstructions != "" { // logic needs to be duplicated in case where no env vars in yaml file.
printDefangHint("Check the files in your favorite editor.\nTo deploy the service, do "+cd, "config set "+envInstructions)
} else {
printDefangHint("Check the files in your favorite editor.\nTo deploy the service, do "+cd, "compose up")
}

return nil
},
}

func collectUnsetEnvVars(project *proj.Project) []string {
var envVars []string
if project != nil {
for _, service := range project.Services {
for key, value := range service.Environment {
if value == nil {
envVars = append(envVars, key)
}
}
}
}
return envVars
}

var getServicesCmd = &cobra.Command{
Use: "services",
Annotations: authNeededAnnotation,
Expand Down

0 comments on commit 54bf92a

Please sign in to comment.