Skip to content

Commit 5bc324f

Browse files
authored
Merge pull request #1372 from snyk/feat/add_fmt_cmd
Add `driftctl fmt` command
2 parents f2f846d + 69b9702 commit 5bc324f

21 files changed

+813
-404
lines changed

pkg/analyser/analysis.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type serializableDifference struct {
5454
}
5555

5656
type serializableAnalysis struct {
57+
Options AnalyzerOptions `json:"options"`
5758
Summary Summary `json:"summary"`
5859
Managed []resource.SerializableResource `json:"managed"`
5960
Unmanaged []resource.SerializableResource `json:"unmanaged"`
@@ -108,6 +109,7 @@ func (a Analysis) MarshalJSON() ([]byte, error) {
108109
bla.ProviderName = a.ProviderName
109110
bla.ProviderVersion = a.ProviderVersion
110111
bla.ScanDuration = uint(a.Duration.Seconds())
112+
bla.Options = a.Options()
111113

112114
return json.Marshal(bla)
113115
}
@@ -170,6 +172,7 @@ func (a *Analysis) UnmarshalJSON(bytes []byte) error {
170172
a.ProviderVersion = bla.ProviderVersion
171173
a.SetIaCSourceCount(bla.Summary.TotalIaCSourceCount)
172174
a.Duration = time.Duration(bla.ScanDuration) * time.Second
175+
a.options = bla.Options
173176
return nil
174177
}
175178

pkg/analyser/analyzer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ func (c *ComputedDiffAlert) ShouldIgnoreResource() bool {
3838
}
3939

4040
type AnalyzerOptions struct {
41-
Deep bool
42-
OnlyManaged bool
43-
OnlyUnmanaged bool
41+
Deep bool `json:"deep"`
42+
OnlyManaged bool `json:"only_managed"`
43+
OnlyUnmanaged bool `json:"only_unmanaged"`
4444
}
4545

4646
type Analyzer struct {

pkg/analyser/analyzer_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,9 @@ func TestAnalysis_MarshalJSON(t *testing.T) {
13531353

13541354
func TestAnalysis_UnmarshalJSON(t *testing.T) {
13551355
expected := Analysis{
1356+
options: AnalyzerOptions{
1357+
Deep: true,
1358+
},
13561359
summary: Summary{
13571360
TotalResources: 6,
13581361
TotalDrifted: 1,
@@ -1430,6 +1433,7 @@ func TestAnalysis_UnmarshalJSON(t *testing.T) {
14301433
t.Fatal(err)
14311434
}
14321435
assert.Equal(t, expected, got)
1436+
assert.True(t, got.Options().Deep)
14331437
assert.Equal(t, 33, got.Coverage())
14341438
assert.Equal(t, 2, got.Summary().TotalUnmanaged)
14351439
assert.Equal(t, 2, got.Summary().TotalManaged)

pkg/analyser/testdata/input.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2+
"options": {
3+
"deep": true,
4+
"only_managed": false,
5+
"only_unmanaged": false
6+
},
27
"summary": {
38
"total_resources": 6,
49
"total_changed": 1,

pkg/analyser/testdata/output.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
{
2+
"options": {
3+
"deep": false,
4+
"only_managed": false,
5+
"only_unmanaged": false
6+
},
27
"summary": {
38
"total_resources": 6,
49
"total_changed": 1,

pkg/cmd/driftctl.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func NewDriftctlCmd(build build.BuildInterface) *DriftctlCmd {
6969
cmd.PersistentFlags().BoolP("send-crash-report", "", false, "Enable error reporting. Crash data will be sent to us via Sentry.\nWARNING: may leak sensitive data (please read the documentation for more details)\nThis flag should be used only if an error occurs during execution")
7070

7171
cmd.AddCommand(NewScanCmd(&pkg.ScanOptions{}))
72+
cmd.AddCommand(NewFmtCmd(&pkg.FmtOptions{}))
7273
cmd.AddCommand(NewGenDriftIgnoreCmd())
7374

7475
return cmd

pkg/cmd/flags.go

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/pkg/errors"
8+
cmderrors "github.com/snyk/driftctl/pkg/cmd/errors"
9+
"github.com/snyk/driftctl/pkg/cmd/scan/output"
10+
"github.com/snyk/driftctl/pkg/iac/config"
11+
"github.com/snyk/driftctl/pkg/iac/supplier"
12+
"github.com/snyk/driftctl/pkg/iac/terraform/state/backend"
13+
)
14+
15+
func parseFromFlag(from []string) ([]config.SupplierConfig, error) {
16+
17+
configs := make([]config.SupplierConfig, 0, len(from))
18+
19+
for _, flag := range from {
20+
schemePath := strings.Split(flag, "://")
21+
if len(schemePath) != 2 || schemePath[1] == "" || schemePath[0] == "" {
22+
return nil, errors.Wrapf(
23+
cmderrors.NewUsageError(
24+
fmt.Sprintf(
25+
"\nAccepted schemes are: %s",
26+
strings.Join(supplier.GetSupportedSchemes(), ","),
27+
),
28+
),
29+
"Unable to parse from flag '%s'",
30+
flag,
31+
)
32+
}
33+
34+
scheme := schemePath[0]
35+
path := schemePath[1]
36+
supplierBackend := strings.Split(scheme, "+")
37+
if len(supplierBackend) > 2 {
38+
return nil, errors.Wrapf(
39+
cmderrors.NewUsageError(fmt.Sprintf(
40+
"\nAccepted schemes are: %s",
41+
strings.Join(supplier.GetSupportedSchemes(), ","),
42+
),
43+
),
44+
"Unable to parse from scheme '%s'",
45+
scheme,
46+
)
47+
}
48+
49+
supplierKey := supplierBackend[0]
50+
if !supplier.IsSupplierSupported(supplierKey) {
51+
return nil, errors.Wrapf(
52+
cmderrors.NewUsageError(
53+
fmt.Sprintf(
54+
"\nAccepted values are: %s",
55+
strings.Join(supplier.GetSupportedSuppliers(), ","),
56+
),
57+
),
58+
"Unsupported IaC source '%s'",
59+
supplierKey,
60+
)
61+
}
62+
63+
backendString := ""
64+
if len(supplierBackend) == 2 {
65+
backendString = supplierBackend[1]
66+
if !backend.IsSupported(backendString) {
67+
return nil, errors.Wrapf(
68+
cmderrors.NewUsageError(
69+
fmt.Sprintf(
70+
"\nAccepted values are: %s",
71+
strings.Join(backend.GetSupportedBackends(), ","),
72+
),
73+
),
74+
"Unsupported IaC backend '%s'",
75+
backendString,
76+
)
77+
}
78+
}
79+
80+
configs = append(configs, config.SupplierConfig{
81+
Key: supplierKey,
82+
Backend: backendString,
83+
Path: path,
84+
})
85+
}
86+
87+
return configs, nil
88+
}
89+
90+
func parseOutputFlags(out []string) ([]output.OutputConfig, error) {
91+
result := make([]output.OutputConfig, 0, len(out))
92+
for _, v := range out {
93+
o, err := parseOutputFlag(v)
94+
if err != nil {
95+
return result, err
96+
}
97+
result = append(result, *o)
98+
}
99+
return result, nil
100+
}
101+
102+
func parseOutputFlag(out string) (*output.OutputConfig, error) {
103+
schemeOpts := strings.Split(out, "://")
104+
if len(schemeOpts) < 2 || schemeOpts[0] == "" {
105+
return nil, errors.Wrapf(
106+
cmderrors.NewUsageError(
107+
fmt.Sprintf(
108+
"\nAccepted formats are: %s",
109+
strings.Join(output.SupportedOutputsExample(), ","),
110+
),
111+
),
112+
"Unable to parse output flag '%s'",
113+
out,
114+
)
115+
}
116+
117+
o := &output.OutputConfig{
118+
Key: schemeOpts[0],
119+
}
120+
if !output.IsSupported(o.Key) {
121+
return nil, errors.Wrapf(
122+
cmderrors.NewUsageError(
123+
fmt.Sprintf(
124+
"\nValid formats are: %s",
125+
strings.Join(output.SupportedOutputsExample(), ","),
126+
),
127+
),
128+
"Unsupported output '%s'",
129+
o.Key,
130+
)
131+
}
132+
133+
opts := schemeOpts[1:]
134+
135+
switch o.Key {
136+
case output.JSONOutputType:
137+
if len(opts) != 1 || opts[0] == "" {
138+
return nil, errors.Wrapf(
139+
cmderrors.NewUsageError(
140+
fmt.Sprintf(
141+
"\nMust be of kind: %s",
142+
output.Example(output.JSONOutputType),
143+
),
144+
),
145+
"Invalid json output '%s'",
146+
out,
147+
)
148+
}
149+
o.Path = opts[0]
150+
case output.HTMLOutputType:
151+
if len(opts) != 1 || opts[0] == "" {
152+
return nil, errors.Wrapf(
153+
cmderrors.NewUsageError(
154+
fmt.Sprintf(
155+
"\nMust be of kind: %s",
156+
output.Example(output.HTMLOutputType),
157+
),
158+
),
159+
"Invalid html output '%s'",
160+
out,
161+
)
162+
}
163+
o.Path = opts[0]
164+
case output.PlanOutputType:
165+
if len(opts) != 1 || opts[0] == "" {
166+
return nil, errors.Wrapf(
167+
cmderrors.NewUsageError(
168+
fmt.Sprintf(
169+
"\nMust be of kind: %s",
170+
output.Example(output.PlanOutputType),
171+
),
172+
),
173+
"Invalid plan output '%s'",
174+
out,
175+
)
176+
}
177+
o.Path = opts[0]
178+
}
179+
180+
return o, nil
181+
}

0 commit comments

Comments
 (0)