Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/plugin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"

"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/cli/adv2v2"
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/cli/clu2adv"
"github.com/spf13/cobra"
)
Expand All @@ -15,6 +16,7 @@ func main() {
Aliases: []string{"tf"},
}
terraformCmd.AddCommand(clu2adv.Builder())
terraformCmd.AddCommand(adv2v2.Builder())

completionOption := &cobra.CompletionOptions{
DisableDefaultCmd: true,
Expand Down
25 changes: 25 additions & 0 deletions internal/cli/adv2v2/adv2v2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package adv2v2

import (
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/cli"
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/convert"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)

func Builder() *cobra.Command {
o := &cli.BaseOpts{
Fs: afero.NewOsFs(),
Convert: convert.AdvancedClusterToV2,
}
cmd := &cobra.Command{
Use: "advancedClusterToV2",
Short: "Convert advanced_cluster from provider version 1 to 2",
Long: "Convert a Terraform configuration from mongodbatlas_advanced_cluster in provider version 1.X.X (SDKv2)" +
" to version 2.X.X (TPF - Terraform Plugin Framework)",
Aliases: []string{"adv2v2"},
RunE: o.RunE,
}
cli.SetupCommonFlags(cmd, o)
return cmd
}
30 changes: 15 additions & 15 deletions internal/cli/clu2adv/clu2adv.go
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
package clu2adv

import (
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/cli"
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/convert"
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/flag"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)

func Builder() *cobra.Command {
o := &opts{fs: afero.NewOsFs()}
o := &struct {
*cli.BaseOpts
includeMoved bool
}{
BaseOpts: &cli.BaseOpts{
Fs: afero.NewOsFs(),
},
}
o.Convert = func(config []byte) ([]byte, error) {
return convert.ClusterToAdvancedCluster(config, o.includeMoved)
}
cmd := &cobra.Command{
Use: "clusterToAdvancedCluster",
Short: "Convert cluster to advanced_cluster preview provider 2.0.0",
Long: "Convert a Terraform configuration from mongodbatlas_cluster to " +
"mongodbatlas_advanced_cluster preview provider 2.0.0",
Aliases: []string{"clu2adv"},
RunE: func(_ *cobra.Command, _ []string) error {
if err := o.PreRun(); err != nil {
return err
}
return o.Run()
},
RunE: o.RunE,
}
cmd.Flags().StringVarP(&o.file, flag.File, flag.FileShort, "", "input file")
_ = cmd.MarkFlagRequired(flag.File)
cmd.Flags().StringVarP(&o.output, flag.Output, flag.OutputShort, "", "output file")
_ = cmd.MarkFlagRequired(flag.Output)
cmd.Flags().BoolVarP(&o.replaceOutput, flag.ReplaceOutput, flag.ReplaceOutputShort, false,
"replace output file if exists")
cmd.Flags().BoolVarP(&o.watch, flag.Watch, flag.WatchShort, false,
"keeps the plugin running and watches the input file for changes")
cli.SetupCommonFlags(cmd, o.BaseOpts)
cmd.Flags().BoolVarP(&o.includeMoved, flag.IncludeMoved, flag.IncludeMovedShort, false,
"include moved blocks in the output file")
return cmd
Expand Down
97 changes: 0 additions & 97 deletions internal/cli/clu2adv/opts.go

This file was deleted.

130 changes: 130 additions & 0 deletions internal/cli/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package cli
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice re-use!


import (
"errors"
"fmt"

"github.com/fsnotify/fsnotify"
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/file"
"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/flag"
"github.com/spf13/afero"
"github.com/spf13/cobra"
)

type ConvertFn func(config []byte) ([]byte, error)

// BaseOpts contains common functionality for CLI commands that convert files.
type BaseOpts struct {
Fs afero.Fs
Convert ConvertFn
File string
Output string
ReplaceOutput bool
Watch bool
}

// RunE is the entry point for the command.
func (o *BaseOpts) RunE(cmd *cobra.Command, args []string) error {
if err := o.preRun(); err != nil {
return err
}
return o.run()
}

// preRun validates the input and output files before running the command.
func (o *BaseOpts) preRun() error {
if err := file.MustExist(o.Fs, o.File); err != nil {
return err
}
if !o.ReplaceOutput {
return file.MustNotExist(o.Fs, o.Output)
}
return nil
}

// run executes the conversion and optionally watches for file changes.
func (o *BaseOpts) run() error {
if err := o.generateFile(false); err != nil {
return err
}
if o.Watch {
return o.watchFile()
}
return nil
}

// generateFile reads the input file, converts it, and writes the output.
func (o *BaseOpts) generateFile(allowParseErrors bool) error {
inConfig, err := afero.ReadFile(o.Fs, o.File)
if err != nil {
return fmt.Errorf("failed to read file %s: %w", o.File, err)
}

outConfig, err := o.Convert(inConfig)
if err != nil {
if allowParseErrors {
outConfig = []byte("# CONVERT ERROR: " + err.Error() + "\n\n")
outConfig = append(outConfig, inConfig...)
} else {
return err
}
}

if err := afero.WriteFile(o.Fs, o.Output, outConfig, 0o600); err != nil {
return fmt.Errorf("failed to write file %s: %w", o.Output, err)
}
return nil
}

// watchFile watches the input file for changes and regenerates the output.
func (o *BaseOpts) watchFile() error {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
defer watcher.Close()

if err := watcher.Add(o.File); err != nil {
return err
}

for {
if err := o.waitForFileEvent(watcher); err != nil {
return err
}
}
}

// waitForFileEvent waits for file system events and regenerates the output file.
func (o *BaseOpts) waitForFileEvent(watcher *fsnotify.Watcher) error {
watcherError := errors.New("watcher has been closed")
select {
case event, ok := <-watcher.Events:
if !ok {
return watcherError
}
if event.Has(fsnotify.Write) {
if err := o.generateFile(true); err != nil {
return err
}
}
case err, ok := <-watcher.Errors:
if !ok {
return watcherError
}
return err
}
return nil
}

// SetupCommonFlags sets up the common flags used by all commands.
func SetupCommonFlags(cmd *cobra.Command, opts *BaseOpts) {
cmd.Flags().StringVarP(&opts.File, flag.File, flag.FileShort, "", "input file")
_ = cmd.MarkFlagRequired(flag.File)
cmd.Flags().StringVarP(&opts.Output, flag.Output, flag.OutputShort, "", "output file")
_ = cmd.MarkFlagRequired(flag.Output)
cmd.Flags().BoolVarP(&opts.ReplaceOutput, flag.ReplaceOutput, flag.ReplaceOutputShort, false,
"replace output file if exists")
cmd.Flags().BoolVarP(&opts.Watch, flag.Watch, flag.WatchShort, false,
"keeps the plugin running and watches the input file for changes")
}
15 changes: 15 additions & 0 deletions internal/convert/adv2v2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package convert

import "github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/hcl"

// AdvancedClusterToV2 transforms all mongodbatlas_advanced_cluster resource definitions in a
// Terraform configuration file from SDKv2 schema to TPF (Terraform Plugin Framework) schema.
// All other resources and data sources are left untouched.
// TODO: Not implemented yet.
func AdvancedClusterToV2(config []byte) ([]byte, error) {
parser, err := hcl.GetParser(config)
if err != nil {
return nil, err
}
return parser.Bytes(), nil
}
13 changes: 13 additions & 0 deletions internal/convert/adv2v2_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package convert_test

import (
"testing"

"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/convert"
)

func TestAdvancedClusterToV2(t *testing.T) {
runConvertTests(t, "adv2v2", func(testName string, inConfig []byte) ([]byte, error) {
return convert.AdvancedClusterToV2(inConfig)
})
}
File renamed without changes.
15 changes: 15 additions & 0 deletions internal/convert/clu2adv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package convert_test

import (
"strings"
"testing"

"github.com/mongodb-labs/atlas-cli-plugin-terraform/internal/convert"
)

func TestClusterToAdvancedCluster(t *testing.T) {
runConvertTests(t, "clu2adv", func(testName string, inConfig []byte) ([]byte, error) {
includeMoved := strings.Contains(testName, "includeMoved")
return convert.ClusterToAdvancedCluster(inConfig, includeMoved)
})
}
Loading