Skip to content

Commit ce71c3a

Browse files
Merge branch 'awslabs:main' into soci-instrumentation
2 parents 11a968e + 73dd46e commit ce71c3a

7 files changed

Lines changed: 101 additions & 19 deletions

File tree

config/config.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
package config
4040

4141
import (
42+
"errors"
4243
"fmt"
4344
"os"
4445

@@ -84,8 +85,8 @@ func NewConfig() *Config {
8485

8586
// Set any defaults which do not align with Go zero values.
8687
var initParsers = []configParser{defaultPullModes, defaultDirectoryCacheConfig}
87-
for _, p := range append(initParsers, parsers...) {
88-
p(cfg)
88+
if err := parseConfig(cfg, append(initParsers, parsers...)); err != nil {
89+
return nil
8990
}
9091

9192
return cfg
@@ -102,18 +103,26 @@ func NewConfigFromToml(cfgPath string) (*Config, error) {
102103
defer f.Close()
103104

104105
cfg := NewConfig()
106+
if cfg == nil {
107+
return nil, errors.New("error creating default config")
108+
}
105109
// Get configuration from specified file
106110
if err = toml.NewDecoder(f).Decode(cfg); err != nil {
107111
return nil, fmt.Errorf("failed to load config file %q: %w", cfgPath, err)
108112
}
109-
parseConfig(cfg)
113+
if err := parseConfig(cfg, parsers); err != nil {
114+
return nil, fmt.Errorf("config file at %q: %w", cfgPath, err)
115+
}
110116
return cfg, nil
111117
}
112118

113-
func parseConfig(cfg *Config) {
114-
for _, p := range parsers {
115-
p(cfg)
119+
func parseConfig(cfg *Config, cfgParsers []configParser) error {
120+
for _, p := range cfgParsers {
121+
if err := p(cfg); err != nil {
122+
return fmt.Errorf("failed to parse config: %v", err)
123+
}
116124
}
125+
return nil
117126
}
118127

119128
func parseRootConfig(cfg *Config) error {

config/config_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,18 @@ concurrent_download_chunk_size = "1MB"
265265
}
266266
},
267267
},
268+
{
269+
name: "IncorrectChunkConfig",
270+
config: []byte(`
271+
[pull_modes.parallel_pull_unpack]
272+
concurrent_download_chunk_size = "badchunksize"
273+
`),
274+
assert: func(t *testing.T, actual *Config, err error) {
275+
if err == nil {
276+
t.Error("Expected error, got none")
277+
}
278+
},
279+
},
268280
}
269281

270282
for _, test := range tests {

docs/soci-index-manifest-v2.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ There are some use-cases where the dynamic nature of SOCI Index Manifest v1 adds
4545
If you would like to enable SOCI v1, you can add the following to the soci snapshotter config (located at `/var/lib/soci-snapshotter-grpc/config.toml`):
4646

4747
```
48-
[pull_modes.soci_v1]
49-
enable = true
48+
[pull_modes]
49+
[pull_modes.soci_v1]
50+
enable = true
5051
```
5152

5253
## Comparing SOCI Index Manifest v1 and SOCI Index Manifest v2

integration/pull_test.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -885,11 +885,7 @@ func TestPullWithParallelism(t *testing.T) {
885885
},
886886
{
887887
name: "set chunk size",
888-
opts: []snapshotterConfigOpt{
889-
func(cfg *config.Config) {
890-
cfg.PullModes.Parallel.ConcurrentDownloadChunkSize = 1_000_000
891-
},
892-
},
888+
opts: []snapshotterConfigOpt{withConcurrentDownloadChunkSize(1_000_000)},
893889
},
894890
}
895891

@@ -902,11 +898,7 @@ func TestPullWithParallelism(t *testing.T) {
902898
},
903899
{
904900
name: "parallel unpacking",
905-
opts: []snapshotterConfigOpt{
906-
func(cfg *config.Config) {
907-
cfg.PullModes.Parallel.MaxConcurrentUnpacks = 3
908-
},
909-
},
901+
opts: []snapshotterConfigOpt{withConcurrentUnpacks(3)},
910902
},
911903
}
912904

integration/startup_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ import (
2121
"regexp"
2222
"strings"
2323
"testing"
24+
"time"
2425

2526
"github.com/awslabs/soci-snapshotter/config"
2627
shell "github.com/awslabs/soci-snapshotter/util/dockershell"
28+
"github.com/awslabs/soci-snapshotter/util/testutil"
2729
"github.com/rs/xid"
2830
)
2931

@@ -137,3 +139,47 @@ func TestSnapshotterSystemdStartup(t *testing.T) {
137139
})
138140
}
139141
}
142+
143+
// TestSnapshotterStartupWithBadConfig ensures snapshotter does not start if snapshotter values are incorrect.
144+
// Note that incorrect fields are ignored by TOML and thus are expected to work
145+
func TestSnapshotterStartupWithBadConfig(t *testing.T) {
146+
tests := []struct {
147+
name string
148+
opts []snapshotterConfigOpt
149+
expectedErrStr string
150+
}{
151+
{
152+
name: "Bad parallel pull size",
153+
opts: []snapshotterConfigOpt{withParallelPullMode(), withConcurrentDownloadChunkSizeStr("badstring")},
154+
expectedErrStr: "invalid size format",
155+
},
156+
}
157+
158+
for _, tc := range tests {
159+
t.Run(tc.name, func(tt *testing.T) {
160+
sh, cleanup := newSnapshotterBaseShell(t)
161+
defer cleanup()
162+
// rebootContainerd would be ideal here, but that always uses a config,
163+
// so we just manually start SOCI with/without a config file.
164+
err := testutil.KillMatchingProcess(sh, "soci-snapshotter-grpc")
165+
if err != nil {
166+
sh.Fatal("failed to kill soci: %v", err)
167+
}
168+
configToml := getSnapshotterConfigToml(t, tc.opts...)
169+
snRunCmd := []string{"/usr/local/bin/soci-snapshotter-grpc", "--log-level", sociLogLevel}
170+
snRunCmd = addConfig(t, sh, configToml, snRunCmd...)
171+
172+
errCh := make(chan error, 1)
173+
go func() {
174+
_, err := sh.OLog(snRunCmd...)
175+
errCh <- err
176+
}()
177+
178+
select {
179+
case <-errCh:
180+
case <-time.After(2 * time.Second):
181+
t.Fatalf("expected err %s but snapshotter did not fail within 2 seconds", tc.expectedErrStr)
182+
}
183+
})
184+
}
185+
}

integration/util_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,24 @@ func withUnboundedPullUnpack() snapshotterConfigOpt {
377377
}
378378
}
379379

380+
func withConcurrentDownloadChunkSize(chunkSize int64) snapshotterConfigOpt {
381+
return func(c *config.Config) {
382+
c.PullModes.Parallel.ConcurrentDownloadChunkSize = chunkSize
383+
}
384+
}
385+
386+
func withConcurrentDownloadChunkSizeStr(chunkSizeStr string) snapshotterConfigOpt {
387+
return func(c *config.Config) {
388+
c.PullModes.Parallel.ConcurrentDownloadChunkSizeStr = chunkSizeStr
389+
}
390+
}
391+
392+
func withConcurrentUnpacks(n int64) snapshotterConfigOpt {
393+
return func(c *config.Config) {
394+
c.PullModes.Parallel.MaxConcurrentUnpacks = n
395+
}
396+
}
397+
380398
func withDiscardUnpackedLayers() snapshotterConfigOpt {
381399
return func(c *config.Config) {
382400
c.PullModes.Parallel.DiscardUnpackedLayers = true

soci/store/store.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,11 @@ func (s *ContainerdStore) Push(ctx context.Context, expected ocispec.Descriptor,
334334
return fmt.Errorf("unexpected copy size %d, expected %d: %w", totalWritten, expected.Size, errdefs.ErrFailedPrecondition)
335335
}
336336

337-
return writer.Commit(ctx, expected.Size, expected.Digest)
337+
err = writer.Commit(ctx, expected.Size, expected.Digest)
338+
if err != nil && !errors.Is(err, errdefs.ErrAlreadyExists) {
339+
return err
340+
}
341+
return nil
338342
}
339343

340344
// LabelGCRoot labels the target resource to prevent garbage collection of itself.

0 commit comments

Comments
 (0)