2020-12-09 15:31:34 +00:00
package cmd
import (
"fmt"
"reflect"
"testing"
"github.com/cloudskiff/driftctl/pkg/cmd/scan/output"
"github.com/cloudskiff/driftctl/pkg/iac/config"
"github.com/cloudskiff/driftctl/test"
"github.com/spf13/cobra"
)
// TODO: Test successful scan
func TestScanCmd ( t * testing . T ) {
rootCmd := & cobra . Command { Use : "root" }
rootCmd . AddCommand ( NewScanCmd ( ) )
// test.Execute(rootCmd, "scan")
}
func TestScanCmd_Valid ( t * testing . T ) {
rootCmd := & cobra . Command { Use : "root" }
scanCmd := NewScanCmd ( )
scanCmd . RunE = func ( _ * cobra . Command , args [ ] string ) error { return nil }
rootCmd . AddCommand ( scanCmd )
cases := [ ] struct {
args [ ] string
} {
{ args : [ ] string { "scan" } } ,
{ args : [ ] string { "scan" , "-t" , "aws+tf" } } ,
{ args : [ ] string { "scan" , "--to" , "aws+tf" } } ,
{ args : [ ] string { "scan" , "-f" , "tfstate://test" } } ,
{ args : [ ] string { "scan" , "--from" , "tfstate://test" } } ,
2021-01-15 11:44:13 +00:00
{ args : [ ] string { "scan" , "--from" , "tfstate://test" , "--from" , "tfstate://test2" } } ,
2020-12-09 15:31:34 +00:00
{ args : [ ] string { "scan" , "-t" , "aws+tf" , "-f" , "tfstate://test" } } ,
{ args : [ ] string { "scan" , "--to" , "aws+tf" , "--from" , "tfstate://test" } } ,
2021-03-16 15:35:28 +00:00
{ args : [ ] string { "scan" , "--to" , "aws+tf" , "--from" , "tfstate+https://github.com/state.tfstate" } } ,
2021-04-24 21:31:57 +00:00
{ args : [ ] string { "scan" , "--to" , "aws+tf" , "--from" , "tfstate+tfcloud://workspace_id" } } ,
2021-04-30 14:42:05 +00:00
{ args : [ ] string { "scan" , "--tfc-token" , "token" } } ,
2020-12-09 15:31:34 +00:00
{ args : [ ] string { "scan" , "--filter" , "Type=='aws_s3_bucket'" } } ,
2021-03-29 14:00:15 +00:00
{ args : [ ] string { "scan" , "--strict" } } ,
2021-07-20 12:42:52 +00:00
{ args : [ ] string { "scan" , "--deep" } } ,
2021-06-04 11:49:31 +00:00
{ args : [ ] string { "scan" , "--tf-provider-version" , "1.2.3" } } ,
{ args : [ ] string { "scan" , "--tf-provider-version" , "3.30.2" } } ,
2021-06-17 13:39:31 +00:00
{ args : [ ] string { "scan" , "--driftignore" , "./path/to/driftignore.s3" } } ,
{ args : [ ] string { "scan" , "--driftignore" , ".driftignore" } } ,
2020-12-09 15:31:34 +00:00
}
for _ , tt := range cases {
output , err := test . Execute ( rootCmd , tt . args ... )
if output != "" {
t . Errorf ( "Unexpected output: %v" , output )
}
if err != nil {
t . Errorf ( "Unexpected error: %v" , err )
}
}
}
func TestScanCmd_Invalid ( t * testing . T ) {
cases := [ ] struct {
args [ ] string
expected string
} {
{ args : [ ] string { "scan" , "test" } , expected : ` unknown command "test" for "root scan" ` } ,
{ args : [ ] string { "scan" , "-e" } , expected : ` unknown shorthand flag: 'e' in -e ` } ,
{ args : [ ] string { "scan" , "--error" } , expected : ` unknown flag: --error ` } ,
{ args : [ ] string { "scan" , "-t" } , expected : ` flag needs an argument: 't' in -t ` } ,
2021-08-04 15:17:27 +00:00
{ args : [ ] string { "scan" , "-t" , "glou" } , expected : "unsupported cloud provider 'glou'\nValid values are: aws+tf,github+tf,gcp+tf" } ,
2020-12-09 15:31:34 +00:00
{ args : [ ] string { "scan" , "--to" } , expected : ` flag needs an argument: --to ` } ,
2021-08-04 15:17:27 +00:00
{ args : [ ] string { "scan" , "--to" , "glou" } , expected : "unsupported cloud provider 'glou'\nValid values are: aws+tf,github+tf,gcp+tf" } ,
2020-12-09 15:31:34 +00:00
{ args : [ ] string { "scan" , "-f" } , expected : ` flag needs an argument: 'f' in -f ` } ,
{ args : [ ] string { "scan" , "--from" } , expected : ` flag needs an argument: --from ` } ,
{ args : [ ] string { "scan" , "--from" } , expected : ` flag needs an argument: --from ` } ,
2021-04-25 22:33:36 +00:00
{ args : [ ] string { "scan" , "--from" , "tosdgjhgsdhgkjs" } , expected : "Unable to parse from flag 'tosdgjhgsdhgkjs': \nAccepted schemes are: tfstate://,tfstate+s3://,tfstate+http://,tfstate+https://,tfstate+tfcloud://" } ,
{ args : [ ] string { "scan" , "--from" , "://" } , expected : "Unable to parse from flag '://': \nAccepted schemes are: tfstate://,tfstate+s3://,tfstate+http://,tfstate+https://,tfstate+tfcloud://" } ,
{ args : [ ] string { "scan" , "--from" , "://test" } , expected : "Unable to parse from flag '://test': \nAccepted schemes are: tfstate://,tfstate+s3://,tfstate+http://,tfstate+https://,tfstate+tfcloud://" } ,
{ args : [ ] string { "scan" , "--from" , "tosdgjhgsdhgkjs://" } , expected : "Unable to parse from flag 'tosdgjhgsdhgkjs://': \nAccepted schemes are: tfstate://,tfstate+s3://,tfstate+http://,tfstate+https://,tfstate+tfcloud://" } ,
{ args : [ ] string { "scan" , "--from" , "terraform+foo+bar://test" } , expected : "Unable to parse from scheme 'terraform+foo+bar': \nAccepted schemes are: tfstate://,tfstate+s3://,tfstate+http://,tfstate+https://,tfstate+tfcloud://" } ,
2021-02-09 19:03:35 +00:00
{ args : [ ] string { "scan" , "--from" , "unsupported://test" } , expected : "Unsupported IaC source 'unsupported': \nAccepted values are: tfstate" } ,
2021-04-25 22:33:36 +00:00
{ args : [ ] string { "scan" , "--from" , "tfstate+foobar://test" } , expected : "Unsupported IaC backend 'foobar': \nAccepted values are: s3,http,https,tfcloud" } ,
{ args : [ ] string { "scan" , "--from" , "tfstate:///tmp/test" , "--from" , "tfstate+toto://test" } , expected : "Unsupported IaC backend 'toto': \nAccepted values are: s3,http,https,tfcloud" } ,
2020-12-09 15:31:34 +00:00
{ args : [ ] string { "scan" , "--filter" , "Type='test'" } , expected : "unable to parse filter expression: SyntaxError: Expected tRbracket, received: tUnknown" } ,
2021-04-20 11:50:24 +00:00
{ args : [ ] string { "scan" , "--filter" , "Type='test'" , "--filter" , "Type='test2'" } , expected : "Filter flag should be specified only once" } ,
2021-06-04 11:49:31 +00:00
{ args : [ ] string { "scan" , "--tf-provider-version" , ".30.2" } , expected : "Invalid version argument .30.2, expected a valid semver string (e.g. 2.13.4)" } ,
{ args : [ ] string { "scan" , "--tf-provider-version" , "foo" } , expected : "Invalid version argument foo, expected a valid semver string (e.g. 2.13.4)" } ,
2021-06-17 13:39:31 +00:00
{ args : [ ] string { "scan" , "--driftignore" } , expected : "flag needs an argument: --driftignore" } ,
2020-12-09 15:31:34 +00:00
}
for _ , tt := range cases {
rootCmd := & cobra . Command { Use : "root" }
rootCmd . AddCommand ( NewScanCmd ( ) )
_ , err := test . Execute ( rootCmd , tt . args ... )
if err == nil {
t . Errorf ( "Invalid arg should generate error" )
}
if err . Error ( ) != tt . expected {
t . Errorf ( "Expected '%v', got '%v'" , tt . expected , err )
}
}
}
func Test_parseFromFlag ( t * testing . T ) {
type args struct {
2021-01-15 11:44:13 +00:00
from [ ] string
2020-12-09 15:31:34 +00:00
}
tests := [ ] struct {
name string
args args
2021-01-15 11:44:13 +00:00
want [ ] config . SupplierConfig
2020-12-09 15:31:34 +00:00
wantErr bool
} {
{
name : "test complete from parsing" ,
args : args {
2021-01-15 11:44:13 +00:00
from : [ ] string { "tfstate+s3://bucket/path/to/state.tfstate" } ,
2020-12-09 15:31:34 +00:00
} ,
2021-01-15 11:44:13 +00:00
want : [ ] config . SupplierConfig {
{
Key : "tfstate" ,
Backend : "s3" ,
Path : "bucket/path/to/state.tfstate" ,
} ,
} ,
wantErr : false ,
} ,
{
name : "test complete from parsing with multiples flags" ,
args : args {
from : [ ] string { "tfstate+s3://bucket/path/to/state.tfstate" , "tfstate:///tmp/my-state.tfstate" } ,
} ,
want : [ ] config . SupplierConfig {
{
Key : "tfstate" ,
Backend : "s3" ,
Path : "bucket/path/to/state.tfstate" ,
} ,
{
Key : "tfstate" ,
Backend : "" ,
Path : "/tmp/my-state.tfstate" ,
} ,
2020-12-09 15:31:34 +00:00
} ,
wantErr : false ,
} ,
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
got , err := parseFromFlag ( tt . args . from )
if ( err != nil ) != tt . wantErr {
t . Errorf ( "parseFromFlag() error = %v, err %v" , err , tt . wantErr )
return
}
if ! reflect . DeepEqual ( got , tt . want ) {
t . Errorf ( "parseFromFlag() got = %v, want %v" , got , tt . want )
}
} )
}
}
func Test_parseOutputFlag ( t * testing . T ) {
type args struct {
out string
}
tests := [ ] struct {
name string
args args
want * output . OutputConfig
err error
} {
{
name : "test empty" ,
args : args {
out : "" ,
} ,
want : nil ,
2021-06-09 14:06:21 +00:00
err : fmt . Errorf ( "Unable to parse output flag '': \nAccepted formats are: console://,html://PATH/TO/FILE.html,json://PATH/TO/FILE.json,plan://PATH/TO/FILE.json" ) ,
2020-12-09 15:31:34 +00:00
} ,
{
name : "test invalid" ,
args : args {
out : "sdgjsdgjsdg" ,
} ,
want : nil ,
2021-06-09 14:06:21 +00:00
err : fmt . Errorf ( "Unable to parse output flag 'sdgjsdgjsdg': \nAccepted formats are: console://,html://PATH/TO/FILE.html,json://PATH/TO/FILE.json,plan://PATH/TO/FILE.json" ) ,
2020-12-09 15:31:34 +00:00
} ,
{
name : "test invalid" ,
args : args {
out : "://" ,
} ,
want : nil ,
2021-06-09 14:06:21 +00:00
err : fmt . Errorf ( "Unable to parse output flag '://': \nAccepted formats are: console://,html://PATH/TO/FILE.html,json://PATH/TO/FILE.json,plan://PATH/TO/FILE.json" ) ,
2020-12-09 15:31:34 +00:00
} ,
{
name : "test unsupported" ,
args : args {
out : "foobar://" ,
} ,
want : nil ,
2021-06-09 14:06:21 +00:00
err : fmt . Errorf ( "Unsupported output 'foobar': \nValid formats are: console://,html://PATH/TO/FILE.html,json://PATH/TO/FILE.json,plan://PATH/TO/FILE.json" ) ,
2020-12-09 15:31:34 +00:00
} ,
{
name : "test empty json" ,
args : args {
out : "json://" ,
} ,
want : nil ,
2021-02-09 19:03:35 +00:00
err : fmt . Errorf ( "Invalid json output 'json://': \nMust be of kind: json://PATH/TO/FILE.json" ) ,
2020-12-09 15:31:34 +00:00
} ,
{
name : "test valid console" ,
args : args {
out : "console://" ,
} ,
want : & output . OutputConfig {
2021-09-01 08:39:17 +00:00
Key : "console" ,
2020-12-09 15:31:34 +00:00
} ,
err : nil ,
} ,
{
name : "test valid json" ,
args : args {
out : "json:///tmp/foobar.json" ,
} ,
want : & output . OutputConfig {
2021-09-01 08:39:17 +00:00
Key : "json" ,
Path : "/tmp/foobar.json" ,
2020-12-09 15:31:34 +00:00
} ,
err : nil ,
} ,
2021-06-09 14:06:21 +00:00
{
name : "test empty jsonplan" ,
args : args {
out : "plan://" ,
} ,
want : nil ,
err : fmt . Errorf ( "Invalid plan output 'plan://': \nMust be of kind: plan://PATH/TO/FILE.json" ) ,
} ,
{
name : "test valid jsonplan" ,
args : args {
out : "plan:///tmp/foobar.json" ,
} ,
want : & output . OutputConfig {
2021-09-01 08:39:17 +00:00
Key : "plan" ,
Path : "/tmp/foobar.json" ,
2021-06-09 14:06:21 +00:00
} ,
err : nil ,
} ,
2020-12-09 15:31:34 +00:00
}
for _ , tt := range tests {
t . Run ( tt . name , func ( t * testing . T ) {
got , err := parseOutputFlag ( tt . args . out )
if err != nil && err . Error ( ) != tt . err . Error ( ) {
t . Fatalf ( "got error = '%v', expected '%v'" , err , tt . err )
}
if ! reflect . DeepEqual ( got , tt . want ) {
t . Fatalf ( "parseOutputFlag() got = '%v', want '%v'" , got , tt . want )
}
} )
}
}