Skip to content

Commit ebde613

Browse files
committed
fixes#136 feat: Add support for context file, contex command and context switching
Signed-off-by: Harsh4902 <[email protected]>
1 parent 603e58f commit ebde613

File tree

10 files changed

+593
-5
lines changed

10 files changed

+593
-5
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,7 @@
1515
build/dist
1616

1717
# .DS_Store file of MacOS
18-
.DS_Store
18+
.DS_Store
19+
20+
# test data files
21+
**/testdata/**

cmd/cmd.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@ import (
2323
)
2424

2525
var rootCmd = &cobra.Command{
26-
Use: "microcks",
27-
Short: "A CLI tool for Microcks",
28-
Long: `microcks-cli is a CLI for interacting with Microcks server APIs.
29-
It allows to launch tests or import API artifacts with minimal dependencies.`,
26+
Use: "microcks",
27+
Short: "A CLI tool for Microcks",
28+
SilenceUsage: true,
3029
Run: func(cmd *cobra.Command, args []string) {
3130
cmd.HelpFunc()(cmd, args)
3231
},
@@ -48,4 +47,5 @@ func init() {
4847
rootCmd.AddCommand(NewImportURLCommand())
4948
rootCmd.AddCommand(NewStartCommand())
5049
rootCmd.AddCommand(NewStopCommand())
50+
rootCmd.AddCommand(NewContextCommand())
5151
}

cmd/context.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"strings"
8+
"text/tabwriter"
9+
10+
"github.com/microcks/microcks-cli/pkg/config"
11+
"github.com/microcks/microcks-cli/pkg/errors"
12+
"github.com/spf13/cobra"
13+
)
14+
15+
func NewContextCommand() *cobra.Command {
16+
var delete bool
17+
ctxCmd := &cobra.Command{
18+
Use: "context [CONTEXT]",
19+
Aliases: []string{"ctx"},
20+
Short: "switch between contexts",
21+
Example: `# List Microcks context
22+
microcks context/ctx
23+
24+
#Switch Microcks context
25+
microcks context httP://localhost:8080
26+
27+
# Delete Microcks context
28+
microcks context httP://localhost:8080 --delete`,
29+
Run: func(cmd *cobra.Command, args []string) {
30+
var cfgFile string
31+
configPath, err := config.DefaultLocalConfigPath()
32+
errors.CheckError(err)
33+
cfgFile = configPath
34+
localCfg, err := config.ReadLocalConfig(cfgFile)
35+
errors.CheckError(err)
36+
if delete {
37+
if len(args) == 0 {
38+
cmd.HelpFunc()(cmd, args)
39+
os.Exit(1)
40+
}
41+
err := deleteContext(args[0], cfgFile)
42+
errors.CheckError(err)
43+
return
44+
}
45+
46+
if len(args) == 0 {
47+
printMicrocksContexts(cfgFile)
48+
return
49+
}
50+
51+
ctxName := args[0]
52+
if localCfg.CurrentContext == ctxName {
53+
fmt.Printf("Already at context '%s'\n", localCfg.CurrentContext)
54+
return
55+
}
56+
if _, err = localCfg.ResolveContext(ctxName); err != nil {
57+
log.Fatal(err)
58+
}
59+
localCfg.CurrentContext = ctxName
60+
err = config.WriteLocalConfig(*localCfg, configPath)
61+
errors.CheckError(err)
62+
fmt.Printf("Switched to context '%s'\n", localCfg.CurrentContext)
63+
},
64+
}
65+
66+
ctxCmd.Flags().BoolVar(&delete, "delete", false, "Delete a context")
67+
68+
return ctxCmd
69+
}
70+
71+
func deleteContext(context, configPath string) error {
72+
localCfg, err := config.ReadLocalConfig(configPath)
73+
errors.CheckError(err)
74+
if localCfg == nil {
75+
return fmt.Errorf("Nothing to logout from")
76+
}
77+
serverName, ok := localCfg.RemoveContext(context)
78+
if !ok {
79+
return fmt.Errorf("Context %s does not exist", context)
80+
}
81+
_ = localCfg.RemoveUser(context)
82+
_ = localCfg.RemoveServer(serverName)
83+
84+
if localCfg.IsEmpty() {
85+
err := localCfg.DeleteLocalConfig(configPath)
86+
errors.CheckError(err)
87+
} else {
88+
if localCfg.CurrentContext == context {
89+
localCfg.CurrentContext = ""
90+
}
91+
err = config.ValidateLocalConfig(*localCfg)
92+
if err != nil {
93+
return fmt.Errorf("Error in logging out")
94+
}
95+
err = config.WriteLocalConfig(*localCfg, configPath)
96+
errors.CheckError(err)
97+
}
98+
fmt.Printf("Context '%s' deleted\n", context)
99+
return nil
100+
}
101+
102+
func printMicrocksContexts(configPath string) {
103+
localCfg, err := config.ReadLocalConfig(configPath)
104+
errors.CheckError(err)
105+
if localCfg == nil {
106+
log.Fatalf("No contexts defined in %s", configPath)
107+
}
108+
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
109+
defer func() { _ = w.Flush() }()
110+
columnNames := []string{"CURRENT", "NAME", "SERVER"}
111+
_, err = fmt.Fprintf(w, "%s\n", strings.Join(columnNames, "\t"))
112+
errors.CheckError(err)
113+
114+
for _, contextRef := range localCfg.Contexts {
115+
context, err := localCfg.ResolveContext(contextRef.Name)
116+
if err != nil {
117+
log.Printf("Context '%s' had error: %v", contextRef.Name, err)
118+
}
119+
prefix := " "
120+
if localCfg.CurrentContext == context.Name {
121+
prefix = "*"
122+
}
123+
_, err = fmt.Fprintf(w, "%s\t%s\t%s\n", prefix, context.Name, context.Server.Server)
124+
errors.CheckError(err)
125+
}
126+
}

cmd/context_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/microcks/microcks-cli/pkg/config"
8+
"github.com/stretchr/testify/assert"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
const testConfig = `current-context: http://localhost:8083
13+
contexts:
14+
- name: http://localhost:8080
15+
server: http://localhost:8080
16+
user: http://localhost:8080
17+
instance: ""
18+
- name: http://localhost:8083
19+
server: http://localhost:8083
20+
user: http://localhost:8083
21+
instance: ""
22+
servers:
23+
- name: ""
24+
server: http://localhost:8080
25+
insecureTLS: true
26+
keycloakEnable: true
27+
- name: ""
28+
server: http://localhost:8083
29+
insecureTLS: true
30+
keycloakEnable: true
31+
users:
32+
- name: http://localhost:8080
33+
auth-token: vErrYS3c3tReFRe$hToken
34+
refresh-token: vErrYS3c3tReFRe$hToken
35+
- name: http://localhost:8083
36+
auth-token: ""
37+
refresh-token: ""`
38+
39+
const testConfigFilePath = "./testdata/local.config"
40+
41+
func TestDeleteContext(t *testing.T) {
42+
//write the test config file
43+
err := os.WriteFile(testConfigFilePath, []byte(testConfig), os.ModePerm)
44+
require.NoError(t, err)
45+
46+
err = os.Chmod(testConfigFilePath, 0o600)
47+
require.NoError(t, err, "Could not change the file permission to 0600 %v", err)
48+
localCfg, err := config.ReadLocalConfig(testConfigFilePath)
49+
require.NoError(t, err)
50+
assert.Equal(t, "http://localhost:8083", localCfg.CurrentContext)
51+
assert.Contains(t, localCfg.Contexts, config.ContextRef{Name: "http://localhost:8083", Server: "http://localhost:8083", User: "http://localhost:8083", Instance: ""})
52+
53+
//Delete non-current context
54+
err = deleteContext("http://localhost:8080", testConfigFilePath)
55+
require.NoError(t, err)
56+
57+
//Delete current context
58+
err = deleteContext("http://localhost:8083", testConfigFilePath)
59+
require.NoError(t, err)
60+
_, err = config.ReadLocalConfig(testConfigFilePath)
61+
require.NoError(t, err)
62+
}

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ require (
88
github.com/docker/docker v28.0.4+incompatible
99
github.com/docker/go-connections v0.5.0
1010
github.com/spf13/cobra v1.9.1
11+
github.com/stretchr/testify v1.10.0
1112
gopkg.in/yaml.v2 v2.4.0
1213
)
1314

1415
require (
1516
github.com/Microsoft/go-winio v0.4.14 // indirect
1617
github.com/containerd/log v0.1.0 // indirect
18+
github.com/davecgh/go-spew v1.1.1 // indirect
1719
github.com/distribution/reference v0.6.0 // indirect
1820
github.com/docker/go-units v0.5.0 // indirect
1921
github.com/felixge/httpsnoop v1.0.4 // indirect
@@ -27,6 +29,7 @@ require (
2729
github.com/opencontainers/go-digest v1.0.0 // indirect
2830
github.com/opencontainers/image-spec v1.1.1 // indirect
2931
github.com/pkg/errors v0.9.1 // indirect
32+
github.com/pmezard/go-difflib v1.0.0 // indirect
3033
github.com/spf13/pflag v1.0.6 // indirect
3134
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
3235
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
@@ -36,5 +39,6 @@ require (
3639
go.opentelemetry.io/otel/trace v1.35.0 // indirect
3740
golang.org/x/sys v0.30.0 // indirect
3841
golang.org/x/time v0.11.0 // indirect
42+
gopkg.in/yaml.v3 v3.0.1 // indirect
3943
gotest.tools/v3 v3.5.2 // indirect
4044
)

pkg/config/file_permission_unix.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build !windows
2+
3+
package config
4+
5+
import (
6+
"fmt"
7+
"os"
8+
)
9+
10+
func getFilePermission(fi os.FileInfo) error {
11+
if fi.Mode().Perm() == 0o600 || fi.Mode().Perm() == 0o400 {
12+
return nil
13+
}
14+
return fmt.Errorf("config file has incorrect permission flags:%s."+
15+
"change the file permission either to 0400 or 0600.", fi.Mode().Perm().String())
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//go:build windows
2+
3+
package config
4+
5+
import (
6+
"fmt"
7+
"os"
8+
)
9+
10+
func getFilePermission(fi os.FileInfo) error {
11+
if fi.Mode().Perm() == 0666 || fi.Mode().Perm() == 0444 {
12+
return nil
13+
}
14+
return fmt.Errorf("config file has incorrect permission flags:%s."+
15+
"change the file permission either to 0444 or 0666.", fi.Mode().Perm().String())
16+
}

0 commit comments

Comments
 (0)