Skip to content

Commit 2f04ba3

Browse files
committed
feat: #202 Add the --watch flag on import command
Signed-off-by: Laurent Broudoux <[email protected]>
1 parent 30ba696 commit 2f04ba3

File tree

10 files changed

+161
-96
lines changed

10 files changed

+161
-96
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ build-binaries:
2727

2828
.PHONY: build-watcher
2929
build-watcher:
30-
go build -o ${DIST_DIR}/${BIN_NAME}-${WATCHER_NAME} ${PACKAGE}/pkg/importer
30+
go build -o ${DIST_DIR}/${BIN_NAME}-${WATCHER_NAME} ${PACKAGE}/watcher

cmd/import.go

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/microcks/microcks-cli/pkg/config"
2525
"github.com/microcks/microcks-cli/pkg/connectors"
2626
"github.com/microcks/microcks-cli/pkg/errors"
27+
"github.com/microcks/microcks-cli/pkg/watcher"
2728
"github.com/spf13/cobra"
2829
)
2930

@@ -34,6 +35,7 @@ func NewImportCommand(globalClientOpts *connectors.ClientOptions) *cobra.Command
3435
Use: "import",
3536
Short: "import API artifacts on Microcks server",
3637
Long: `import API artifacts on Microcks server`,
38+
Args: cobra.MaximumNArgs(1),
3739
Run: func(cmd *cobra.Command, args []string) {
3840
// Parse subcommand args first.
3941
if len(args) == 0 {
@@ -44,14 +46,23 @@ func NewImportCommand(globalClientOpts *connectors.ClientOptions) *cobra.Command
4446

4547
specificationFiles := args[0]
4648

49+
// Initialize config from command options.
4750
config.InsecureTLS = globalClientOpts.InsecureTLS
4851
config.CaCertPaths = globalClientOpts.CaCertPaths
4952
config.Verbose = globalClientOpts.Verbose
5053

54+
// Read local config file in case we need some context info.
55+
localConfig, err := config.ReadLocalConfig(globalClientOpts.ConfigPath)
56+
if err != nil {
57+
fmt.Println(err)
58+
return
59+
}
60+
61+
// Prepare Microcks client.
5162
var mc connectors.MicrocksClient
5263

5364
if globalClientOpts.ServerAddr != "" && globalClientOpts.ClientId != "" && globalClientOpts.ClientSecret != "" {
54-
// create client with server address
65+
// Create client with server address.
5566
mc = connectors.NewMicrocksClient(globalClientOpts.ServerAddr)
5667

5768
keycloakURL, err := mc.GetKeycloakURL()
@@ -60,7 +71,7 @@ func NewImportCommand(globalClientOpts *connectors.ClientOptions) *cobra.Command
6071
os.Exit(1)
6172
}
6273

63-
var oauthToken string = "unauthentifed-token"
74+
var oauthToken string = "unauthenticated-token"
6475
if keycloakURL != "null" {
6576
// If Keycloak is enabled, retrieve an OAuth token using Keycloak Client.
6677
kc := connectors.NewKeycloakClient(keycloakURL, globalClientOpts.ClientId, globalClientOpts.ClientSecret)
@@ -73,18 +84,23 @@ func NewImportCommand(globalClientOpts *connectors.ClientOptions) *cobra.Command
7384
//fmt.Printf("Retrieve OAuthToken: %s", oauthToken)
7485
}
7586

76-
//Set Auth token
87+
// Set Auth token.
7788
mc.SetOAuthToken(oauthToken)
78-
} else {
7989

80-
localConfig, err := config.ReadLocalConfig(globalClientOpts.ConfigPath)
81-
if err != nil {
82-
fmt.Println(err)
83-
return
90+
// If no context provided use current one from config file or client server address.
91+
// So that watch config can be updated properly, referencing the right context.
92+
if globalClientOpts.Context == "" {
93+
if (localConfig != nil) && (localConfig.CurrentContext != "") {
94+
globalClientOpts.Context = localConfig.CurrentContext
95+
} else {
96+
globalClientOpts.Context = globalClientOpts.ServerAddr
97+
}
8498
}
8599

100+
} else {
101+
// Create client from config file and using the current or provided context.
86102
if localConfig == nil {
87-
fmt.Println("Please login to perform opertion...")
103+
fmt.Println("Please login to perform operation...")
88104
return
89105
}
90106

@@ -98,10 +114,13 @@ func NewImportCommand(globalClientOpts *connectors.ClientOptions) *cobra.Command
98114
return
99115
}
100116
}
117+
118+
// Handle multiple specification files separated by comma.
101119
sepSpecificationFiles := strings.Split(specificationFiles, ",")
102120
for _, f := range sepSpecificationFiles {
103121
mainArtifact := true
104122
var err error
123+
105124
// Check if mainArtifact flag is provided.
106125
if strings.Contains(f, ":") {
107126
pathAndMainArtifact := strings.Split(f, ":")
@@ -118,31 +137,55 @@ func NewImportCommand(globalClientOpts *connectors.ClientOptions) *cobra.Command
118137
fmt.Printf("Got error when invoking Microcks client importing Artifact: %s", err)
119138
os.Exit(1)
120139
}
121-
fmt.Printf("Microcks has discovered '%s'\n", msg)
140+
action := "discovered"
141+
if !mainArtifact {
142+
action = "completed"
143+
}
144+
fmt.Printf("Microcks has %s '%s'\n", action, msg)
122145

146+
// If watch flag is provided, update watch config.
123147
if watch {
124148
watchFile, err := config.DefaultLocalWatchPath()
125149
errors.CheckError(err)
150+
126151
watchCfg, err := config.ReadLocalWatchConfig(watchFile)
127152
errors.CheckError(err)
128153
if watchCfg == nil {
129154
watchCfg = &config.WatchConfig{}
130155
}
131156

157+
// Normalize file path to match the watcher fsnotify events format.
158+
if strings.HasPrefix(f, "./") {
159+
f = strings.TrimPrefix(f, "./")
160+
}
161+
162+
// Upsert entry.
132163
watchCfg.UpsertEntry(config.WatchEntry{
133164
FilePath: f,
134165
Context: []string{globalClientOpts.Context},
135166
MainArtifact: mainArtifact,
136167
})
137-
//write watch file
168+
169+
// Write watch file.
138170
err = config.WriteLocalWatchConfig(*watchCfg, watchFile)
139171
errors.CheckError(err)
140172
}
141173
}
142174

175+
// Start watcher if --watch flag is provided.
176+
if watch {
177+
watchFile, err := config.DefaultLocalWatchPath()
178+
errors.CheckError(err)
179+
180+
wm, err := watcher.NewWatchManger(watchFile)
181+
errors.CheckError(err)
182+
183+
fmt.Println("Watch mode enabled - microcks-watcher started...")
184+
wm.Run()
185+
}
143186
},
144187
}
145188

146-
importCmd.Flags().BoolVar(&watch, "watch", false, "Keep watch on file changes and re-import it on change ")
189+
importCmd.Flags().BoolVar(&watch, "watch", false, "Keep watch on file changes and re-import it on change")
147190
return importCmd
148191
}

cmd/login.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ microcks login http://localhost:8080 --sso --sso-launch-browser=false
160160
})
161161

162162
localConfig.CurrentContext = ctxName
163-
localConfig.UpserContext(config.ContextRef{
163+
localConfig.UpsertContext(config.ContextRef{
164164
Name: ctxName,
165165
Server: server,
166166
User: server,

cmd/start.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ microcks start --name [name of you container/instance]`,
129129
})
130130

131131
localConfig.CurrentContext = server
132-
localConfig.UpserContext(config.ContextRef{
132+
localConfig.UpsertContext(config.ContextRef{
133133
Name: server,
134134
Server: server,
135135
User: server,

pkg/config/localconfig.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ func ReadLocalConfig(path string) (*LocalConfig, error) {
9898

9999
// DefaultConfigDir returns the local configuration path for settings such as cached authentication tokens.
100100
func DefaultConfigDir() (string, error) {
101-
102101
configDir := os.Getenv("MICROCKS_CONFIG_DIR")
103102

104103
if configDir != "" {
@@ -134,6 +133,7 @@ func DefaultLocalConfigPath() (string, error) {
134133
return path.Join(dir, "config"), nil
135134
}
136135

136+
// DefaultLocalWatchPath returns the local watch configuration path.
137137
func DefaultLocalWatchPath() (string, error) {
138138
dir, err := DefaultConfigDir()
139139
if err != nil {
@@ -142,6 +142,7 @@ func DefaultLocalWatchPath() (string, error) {
142142
return path.Join(dir, "watch"), nil
143143
}
144144

145+
// ValidateLocalConfig validates the local configuration.
145146
func ValidateLocalConfig(config LocalConfig) error {
146147
if config.CurrentContext == "" {
147148
return nil
@@ -161,6 +162,7 @@ func WriteLocalConfig(config LocalConfig, configPath string) error {
161162
return configUtil.MarshalLocalYAMLFile(configPath, &config)
162163
}
163164

165+
// DeleteLocalConfig deletes the local configuration file.
164166
func (l *LocalConfig) DeleteLocalConfig(configPath string) error {
165167
_, err := os.Stat(configPath)
166168
if os.IsNotExist(err) {
@@ -202,7 +204,8 @@ func (l *LocalConfig) ResolveContext(name string) (*Context, error) {
202204
return nil, fmt.Errorf("Context '%s' undefined", name)
203205
}
204206

205-
func (l *LocalConfig) UpserContext(context ContextRef) {
207+
// UpsertContext upserts a context reference.
208+
func (l *LocalConfig) UpsertContext(context ContextRef) {
206209
for i, c := range l.Contexts {
207210
if c.Name == context.Name {
208211
l.Contexts[i] = context
@@ -212,6 +215,7 @@ func (l *LocalConfig) UpserContext(context ContextRef) {
212215
l.Contexts = append(l.Contexts, context)
213216
}
214217

218+
// RemoveContext and returns server name and true if context was removed successfully
215219
func (l *LocalConfig) RemoveContext(serverName string) (string, bool) {
216220
for i, c := range l.Contexts {
217221
if c.Name == serverName {
@@ -222,7 +226,7 @@ func (l *LocalConfig) RemoveContext(serverName string) (string, bool) {
222226
return "", false
223227
}
224228

225-
// Returns true if user was removed successfully
229+
// RemoveToken and returns true if user was removed successfully
226230
func (l *LocalConfig) RemoveToken(serverName string) bool {
227231
for i, u := range l.Users {
228232
if u.Name == serverName {
@@ -234,6 +238,7 @@ func (l *LocalConfig) RemoveToken(serverName string) bool {
234238
return false
235239
}
236240

241+
// GetUser retrieves a user by name.
237242
func (l *LocalConfig) GetUser(name string) (*User, error) {
238243
for _, u := range l.Users {
239244
if u.Name == name {
@@ -243,6 +248,7 @@ func (l *LocalConfig) GetUser(name string) (*User, error) {
243248
return nil, fmt.Errorf("User '%s' undefined", name)
244249
}
245250

251+
// UpsertUser upserts a user.
246252
func (l *LocalConfig) UpsertUser(user User) {
247253
for i, u := range l.Users {
248254
if u.Name == user.Name {
@@ -363,6 +369,7 @@ func (l *LocalConfig) RemoveAuth(server string) bool {
363369
return false
364370
}
365371

372+
// UpsertEntry upserts a watch entry.
366373
func (w *WatchConfig) UpsertEntry(entry WatchEntry) {
367374
for i, e := range w.Entries {
368375
if e.FilePath == entry.FilePath {
@@ -377,6 +384,7 @@ func (w *WatchConfig) UpsertEntry(entry WatchEntry) {
377384
w.Entries = append(w.Entries, entry)
378385
}
379386

387+
// ReadLocalWatchConfig loads up the local watch configuration file. Returns nil if config does not exist
380388
func ReadLocalWatchConfig(path string) (*WatchConfig, error) {
381389
var err error
382390
var config WatchConfig
@@ -397,6 +405,7 @@ func ReadLocalWatchConfig(path string) (*WatchConfig, error) {
397405
return &config, nil
398406
}
399407

408+
// WriteLocalWatchConfig writes a new local watch configuration file.
400409
func WriteLocalWatchConfig(config WatchConfig, cfgPath string) error {
401410
err := os.MkdirAll(path.Dir(cfgPath), os.ModePerm)
402411
if err != nil {

pkg/connectors/microcks_client.go

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,32 @@ func NewClient(opts ClientOptions) (MicrocksClient, error) {
168168
return &c, nil
169169
}
170170

171+
// NewMicrocksClient builds a new headless MicrocksClient without any authtoken and all for general purposes
172+
func NewMicrocksClient(apiURL string) MicrocksClient {
173+
mc := microcksClient{}
174+
175+
if !strings.HasSuffix(apiURL, "/api/") {
176+
apiURL += "/api/"
177+
}
178+
179+
u, err := url.Parse(apiURL)
180+
if err != nil {
181+
panic(err)
182+
}
183+
mc.APIURL = u
184+
185+
if config.InsecureTLS || len(config.CaCertPaths) > 0 {
186+
tlsConfig := config.CreateTLSConfig()
187+
tr := &http.Transport{
188+
TLSClientConfig: tlsConfig,
189+
}
190+
mc.httpClient = &http.Client{Transport: tr}
191+
} else {
192+
mc.httpClient = http.DefaultClient
193+
}
194+
return &mc
195+
}
196+
171197
func (c *microcksClient) HttpClient() *http.Client {
172198
return c.httpClient
173199
}
@@ -284,32 +310,6 @@ func (c *microcksClient) redeemRefreshToken(auth config.Auth) (string, string, e
284310
return token.AccessToken, token.RefreshToken, nil
285311
}
286312

287-
// NewMicrocksClient builds a new headless MicrocksClient without any authtoken and all for general purposes
288-
func NewMicrocksClient(apiURL string) MicrocksClient {
289-
mc := microcksClient{}
290-
291-
if !strings.HasSuffix(apiURL, "/api/") {
292-
apiURL += "/api/"
293-
}
294-
295-
u, err := url.Parse(apiURL)
296-
if err != nil {
297-
panic(err)
298-
}
299-
mc.APIURL = u
300-
301-
if config.InsecureTLS || len(config.CaCertPaths) > 0 {
302-
tlsConfig := config.CreateTLSConfig()
303-
tr := &http.Transport{
304-
TLSClientConfig: tlsConfig,
305-
}
306-
mc.httpClient = &http.Client{Transport: tr}
307-
} else {
308-
mc.httpClient = http.DefaultClient
309-
}
310-
return &mc
311-
}
312-
313313
func (c *microcksClient) SetOAuthToken(oauthToken string) {
314314
c.AuthToken = oauthToken
315315
}

pkg/importer/watcher/executor.go

Lines changed: 0 additions & 51 deletions
This file was deleted.

0 commit comments

Comments
 (0)