Skip to content

Commit 1c85f0d

Browse files
Add compact_sequence_indent option for YAML stores
Expose the Go yaml.v3 CompactSeqIndent() encoder setting, which treats '- ' as part of the indentation. With indent: 2, this produces sequences flush with their parent key, matching the style expected by yamlfmt and yamllint. Configurable via .sops.yaml or --compact-sequence-indent flag. Refs #514, #864, #1066 Signed-off-by: david amick <david@davidamick.com>
1 parent cd1d1fd commit 1c85f0d

5 files changed

Lines changed: 139 additions & 1 deletion

File tree

README.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,25 @@ by configuring ``.sops.yaml`` with:
14421442
The YAML emitter used by SOPS only supports values between 2 and 9. If you specify 1,
14431443
or 10 and larger, the indent will be 2.
14441444
1445+
When ``compact_array_indent`` is enabled, the array indicator (``"- "``) is considered
1446+
part of the indentation. Combined with ``indent: 2``, this produces output where arrays are
1447+
flush with their parent key, matching the style used in Kubernetes manifests and YAML linters:
1448+
1449+
.. code:: yaml
1450+
1451+
spec:
1452+
rules:
1453+
- host: example.com
1454+
1455+
You can enable this with the ``--compact-array-indent`` CLI option or by configuring
1456+
``.sops.yaml`` with:
1457+
1458+
.. code:: yaml
1459+
1460+
stores:
1461+
yaml:
1462+
compact_array_indent: true
1463+
14451464
YAML anchors
14461465
~~~~~~~~~~~~
14471466
@@ -2110,6 +2129,10 @@ The store configuration object can have the following keys:
21102129
The YAML emitter used by sops only supports values between ``2`` and ``9``.
21112130
If you specify ``1``, or ``10`` and larger, the indent will be ``2``.
21122131
2132+
* ``compact_array_indent`` (boolean; default ``false``): when enabled, the array
2133+
indicator (``"- "``) is considered part of the indentation. Combined with ``indent: 2``,
2134+
this produces output where arrays are flush with their parent key.
2135+
21132136
Encryption Protocol
21142137
-------------------
21152138

cmd/sops/main.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,10 @@ func main() {
18631863
Name: "indent",
18641864
Usage: "the number of spaces to indent YAML or JSON encoded file",
18651865
},
1866+
cli.BoolFlag{
1867+
Name: "compact-array-indent",
1868+
Usage: "use compact YAML array indentation where '- ' is considered part of the indentation",
1869+
},
18661870
cli.BoolFlag{
18671871
Name: "verbose",
18681872
Usage: "Enable verbose logging output",
@@ -2394,6 +2398,9 @@ func outputStore(context *cli.Context, path string) (common.Store, error) {
23942398
storesConf.JSON.Indent = indent
23952399
storesConf.JSONBinary.Indent = indent
23962400
}
2401+
if context.GlobalBool("compact-array-indent") {
2402+
storesConf.YAML.CompactArrayIndent = true
2403+
}
23972404

23982405
return common.DefaultStoreForPathOrFormat(storesConf, path, context.String("output-type")), nil
23992406
}

config/config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ type JSONBinaryStoreConfig struct {
112112
}
113113

114114
type YAMLStoreConfig struct {
115-
Indent int `yaml:"indent"`
115+
Indent int `yaml:"indent"`
116+
CompactArrayIndent bool `yaml:"compact_array_indent"`
116117
}
117118

118119
type StoresConfig struct {

stores/yaml/store.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) {
397397
return nil, err
398398
}
399399
e.SetIndent(indent)
400+
if store.config.CompactArrayIndent {
401+
e.CompactSeqIndent()
402+
}
400403
for _, branch := range in.Branches {
401404
// Document root
402405
var doc = yaml.Node{}
@@ -433,6 +436,9 @@ func (store *Store) EmitPlainFile(branches sops.TreeBranches) ([]byte, error) {
433436
return nil, err
434437
}
435438
e.SetIndent(indent)
439+
if store.config.CompactArrayIndent {
440+
e.CompactSeqIndent()
441+
}
436442
for _, branch := range branches {
437443
// Document root
438444
var doc = yaml.Node{}

stores/yaml/store_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,107 @@ func TestIndent1(t *testing.T) {
440440
assert.Equal(t, INDENT_1_OUT, bytes)
441441
}
442442

443+
func TestCompactArrayIndent(t *testing.T) {
444+
in := []byte(`spec:
445+
rules:
446+
- host: example.com
447+
http:
448+
paths:
449+
- path: /api
450+
backend:
451+
serviceName: api
452+
- path: /web
453+
backend:
454+
serviceName: web
455+
tags:
456+
- production
457+
- web
458+
`)
459+
// With default indent (4) and CompactSeqIndent, '- ' is considered
460+
// part of the indentation, so arrays are indented by (indent - 2) spaces.
461+
expected := []byte(`spec:
462+
rules:
463+
- host: example.com
464+
http:
465+
paths:
466+
- path: /api
467+
backend:
468+
serviceName: api
469+
- path: /web
470+
backend:
471+
serviceName: web
472+
tags:
473+
- production
474+
- web
475+
`)
476+
branches, err := (&Store{}).LoadPlainFile(in)
477+
assert.Nil(t, err)
478+
bytes, err := (&Store{
479+
config: config.YAMLStoreConfig{
480+
CompactArrayIndent: true,
481+
},
482+
}).EmitPlainFile(branches)
483+
assert.Nil(t, err)
484+
assert.Equal(t, string(expected), string(bytes))
485+
}
486+
487+
func TestCompactArrayIndentWithIndent2(t *testing.T) {
488+
// With indent 2, compact array indent produces arrays flush with the parent key.
489+
in := []byte(`spec:
490+
rules:
491+
- host: example.com
492+
http:
493+
paths:
494+
- path: /api
495+
backend:
496+
serviceName: api
497+
tags:
498+
- production
499+
- web
500+
`)
501+
expected := []byte(`spec:
502+
rules:
503+
- host: example.com
504+
http:
505+
paths:
506+
- path: /api
507+
backend:
508+
serviceName: api
509+
tags:
510+
- production
511+
- web
512+
`)
513+
branches, err := (&Store{}).LoadPlainFile(in)
514+
assert.Nil(t, err)
515+
bytes, err := (&Store{
516+
config: config.YAMLStoreConfig{
517+
Indent: 2,
518+
CompactArrayIndent: true,
519+
},
520+
}).EmitPlainFile(branches)
521+
assert.Nil(t, err)
522+
assert.Equal(t, string(expected), string(bytes))
523+
}
524+
525+
func TestCompactArrayIndentDisabled(t *testing.T) {
526+
in := []byte(`spec:
527+
rules:
528+
- host: example.com
529+
http:
530+
paths:
531+
- path: /api
532+
`)
533+
branches, err := (&Store{}).LoadPlainFile(in)
534+
assert.Nil(t, err)
535+
bytes, err := (&Store{
536+
config: config.YAMLStoreConfig{
537+
CompactArrayIndent: false,
538+
},
539+
}).EmitPlainFile(branches)
540+
assert.Nil(t, err)
541+
assert.Equal(t, string(in), string(bytes))
542+
}
543+
443544
func TestHasSopsTopLevelKey(t *testing.T) {
444545
ok := (&Store{}).HasSopsTopLevelKey(sops.TreeBranch{
445546
sops.TreeItem{

0 commit comments

Comments
 (0)