Skip to content

Commit 153a387

Browse files
authored
feat: Supports watch param (#25)
* rename overwriteOutput param to replaceOutput * watch * watch readme * adjust doc * simplify outConfig with convert errors * join err check * waitForFileEvent
1 parent cb5edda commit 153a387

File tree

5 files changed

+72
-8
lines changed

5 files changed

+72
-8
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ you can also use shorter aliases, e.g.:
3232
atlas tf clu2adv -f in.tf -o out.tf
3333
```
3434

35-
If you want to overwrite the output file if it exists, or even use the same output file as the input file, use the `--overwriteOutput true` or the `-w` flag.
35+
If you want to overwrite the output file if it exists, or even use the same output file as the input file, use the `--replaceOutput true` or the `-r` flag.
36+
37+
You can use the `--watch true` or the `-w` flag to keep the plugin running and watching for changes in the input file. You can have input and output files open in an editor and see easily how changes to the input file affect the output file.
3638

3739
### Limitations
3840

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/mongodb-labs/atlas-cli-plugin-terraform
33
go 1.23.6
44

55
require (
6+
github.com/fsnotify/fsnotify v1.8.0
67
github.com/hashicorp/hcl/v2 v2.23.0
78
github.com/sebdah/goldie/v2 v2.5.5
89
github.com/spf13/afero v1.12.0
@@ -23,6 +24,7 @@ require (
2324
github.com/spf13/pflag v1.0.5 // indirect
2425
golang.org/x/mod v0.22.0 // indirect
2526
golang.org/x/sync v0.10.0 // indirect
27+
golang.org/x/sys v0.29.0 // indirect
2628
golang.org/x/text v0.21.0 // indirect
2729
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
2830
gopkg.in/yaml.v3 v3.0.1 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
66
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
77
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
88
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9+
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
10+
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
911
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
1012
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
1113
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
@@ -49,6 +51,8 @@ golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
4951
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
5052
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
5153
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
54+
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
55+
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
5256
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
5357
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
5458
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=

internal/cli/clu2adv/clu2adv.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func Builder() *cobra.Command {
2323
_ = cmd.MarkFlagRequired("file")
2424
cmd.Flags().StringVarP(&o.output, "output", "o", "", "output file")
2525
_ = cmd.MarkFlagRequired("output")
26-
cmd.Flags().BoolVarP(&o.overwriteOutput, "overwriteOutput", "w", false, "overwrite output file if exists")
26+
cmd.Flags().BoolVarP(&o.replaceOutput, "replaceOutput", "r", false, "replace output file if exists")
27+
cmd.Flags().BoolVarP(&o.watch, "watch", "w", false, "keeps the plugin running and watches the input file for changes")
2728
return cmd
2829
}

internal/cli/clu2adv/opts.go

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,96 @@
11
package clu2adv
22

33
import (
4+
"errors"
45
"fmt"
56

7+
"github.com/fsnotify/fsnotify"
68
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/convert"
79
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/file"
810
"github.com/spf13/afero"
911
)
1012

1113
type opts struct {
12-
fs afero.Fs
13-
file string
14-
output string
15-
overwriteOutput bool
14+
fs afero.Fs
15+
file string
16+
output string
17+
replaceOutput bool
18+
watch bool
1619
}
1720

1821
func (o *opts) PreRun() error {
1922
if err := file.MustExist(o.fs, o.file); err != nil {
2023
return err
2124
}
22-
if !o.overwriteOutput {
25+
if !o.replaceOutput {
2326
return file.MustNotExist(o.fs, o.output)
2427
}
2528
return nil
2629
}
2730

2831
func (o *opts) Run() error {
32+
if err := o.generateFile(false); err != nil {
33+
return err
34+
}
35+
if o.watch {
36+
return o.watchFile()
37+
}
38+
return nil
39+
}
40+
41+
func (o *opts) generateFile(allowParseErrors bool) error {
2942
inConfig, err := afero.ReadFile(o.fs, o.file)
3043
if err != nil {
3144
return fmt.Errorf("failed to read file %s: %w", o.file, err)
3245
}
3346
outConfig, err := convert.ClusterToAdvancedCluster(inConfig)
3447
if err != nil {
35-
return err
48+
if allowParseErrors {
49+
outConfig = []byte("# CONVERT ERROR: " + err.Error() + "\n\n")
50+
outConfig = append(outConfig, inConfig...)
51+
} else {
52+
return err
53+
}
3654
}
3755
if err := afero.WriteFile(o.fs, o.output, outConfig, 0o600); err != nil {
3856
return fmt.Errorf("failed to write file %s: %w", o.output, err)
3957
}
4058
return nil
4159
}
60+
61+
func (o *opts) watchFile() error {
62+
watcher, err := fsnotify.NewWatcher()
63+
if err != nil {
64+
return nil
65+
}
66+
defer watcher.Close()
67+
if err := watcher.Add(o.file); err != nil {
68+
return err
69+
}
70+
for {
71+
if err := o.waitForFileEvent(watcher); err != nil {
72+
return err
73+
}
74+
}
75+
}
76+
77+
func (o *opts) waitForFileEvent(watcher *fsnotify.Watcher) error {
78+
watcherError := errors.New("watcher has been closed")
79+
select {
80+
case event, ok := <-watcher.Events:
81+
if !ok {
82+
return watcherError
83+
}
84+
if event.Has(fsnotify.Write) {
85+
if err := o.generateFile(true); err != nil {
86+
return err
87+
}
88+
}
89+
case err, ok := <-watcher.Errors:
90+
if !ok {
91+
return watcherError
92+
}
93+
return err
94+
}
95+
return nil
96+
}

0 commit comments

Comments
 (0)