Switch config format to be easier to understand
Use a multiple choice instead of trying to keep it to booleans Signed-off-by: James Hewitt <james.hewitt@uk.ibm.com>
This commit is contained in:
parent
db80ebed2d
commit
b6cc51d369
4 changed files with 101 additions and 60 deletions
|
@ -680,6 +680,8 @@ type Validation struct {
|
||||||
Disabled bool `yaml:"disabled,omitempty"`
|
Disabled bool `yaml:"disabled,omitempty"`
|
||||||
// Manifests configures manifest validation.
|
// Manifests configures manifest validation.
|
||||||
Manifests ValidationManifests `yaml:"manifests,omitempty"`
|
Manifests ValidationManifests `yaml:"manifests,omitempty"`
|
||||||
|
// ImageIndexes configures validation of image indexes
|
||||||
|
ImageIndexes ValidationImageIndexes `yaml:"imageindexes,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValidationManifests struct {
|
type ValidationManifests struct {
|
||||||
|
@ -692,18 +694,38 @@ type ValidationManifests struct {
|
||||||
// that URLs in pushed manifests must not match.
|
// that URLs in pushed manifests must not match.
|
||||||
Deny []string `yaml:"deny,omitempty"`
|
Deny []string `yaml:"deny,omitempty"`
|
||||||
} `yaml:"urls,omitempty"`
|
} `yaml:"urls,omitempty"`
|
||||||
// ImageIndex configures validation of image indexes
|
|
||||||
ImageIndex ValidationManifestsImageIndex `yaml:"imageindex,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ValidationManifestsImageIndex struct {
|
type ValidationImageIndexes struct {
|
||||||
Images struct {
|
// PlatformsExist configures the validation applies to the platform images included in an image index
|
||||||
// Exist validates that images referenced by indexes exist in the registry
|
PlatformsExist PlatformsExist `yaml:"platformsexist"`
|
||||||
// before the image index is accepted.
|
// SelectedPlatforms filters the set of platforms to validate for image existence.
|
||||||
Exist *bool `yaml:"exist"`
|
SelectedPlatforms []Platform `yaml:"selectedplatforms,omitempty"`
|
||||||
// Platforms filters the set of platforms to validate for image existence.
|
}
|
||||||
Platforms []Platform `yaml:"platforms,omitempty"`
|
|
||||||
} `yaml:"images,omitempty"`
|
// PlatformsExist configures the validation applies to the platform images included in an image index
|
||||||
|
// This can be all, none, or selected
|
||||||
|
type PlatformsExist string
|
||||||
|
|
||||||
|
// UnmarshalYAML implements the yaml.Umarshaler interface
|
||||||
|
// Unmarshals a string into a PlatformsExist option, lowercasing the string and validating that it represents a
|
||||||
|
// valid option
|
||||||
|
func (platformsexist *PlatformsExist) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var platformsExistString string
|
||||||
|
err := unmarshal(&platformsExistString)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
platformsExistString = strings.ToLower(platformsExistString)
|
||||||
|
switch platformsExistString {
|
||||||
|
case "all", "none", "selected":
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid platformsexist option %s Must be one of [all, none, selected]", platformsExistString)
|
||||||
|
}
|
||||||
|
|
||||||
|
*platformsexist = PlatformsExist(platformsExistString)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses an input configuration yaml document into a Configuration struct
|
// Parse parses an input configuration yaml document into a Configuration struct
|
||||||
|
|
|
@ -16,9 +16,6 @@ import (
|
||||||
// Hook up gocheck into the "go test" runner
|
// Hook up gocheck into the "go test" runner
|
||||||
func Test(t *testing.T) { check.TestingT(t) }
|
func Test(t *testing.T) { check.TestingT(t) }
|
||||||
|
|
||||||
// falseaddr is a boolean false to reference
|
|
||||||
var falseaddr = false
|
|
||||||
|
|
||||||
// configStruct is a canonical example configuration, which should map to configYamlV0_1
|
// configStruct is a canonical example configuration, which should map to configYamlV0_1
|
||||||
var configStruct = Configuration{
|
var configStruct = Configuration{
|
||||||
Version: "0.1",
|
Version: "0.1",
|
||||||
|
@ -169,15 +166,8 @@ var configStruct = Configuration{
|
||||||
WriteTimeout: time.Millisecond * 10,
|
WriteTimeout: time.Millisecond * 10,
|
||||||
},
|
},
|
||||||
Validation: Validation{
|
Validation: Validation{
|
||||||
Manifests: ValidationManifests{
|
ImageIndexes: ValidationImageIndexes{
|
||||||
ImageIndex: ValidationManifestsImageIndex{
|
PlatformsExist: "none",
|
||||||
Images: struct {
|
|
||||||
Exist *bool `yaml:"exist"`
|
|
||||||
Platforms []Platform `yaml:"platforms,omitempty"`
|
|
||||||
}{
|
|
||||||
Exist: &falseaddr,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -237,10 +227,8 @@ redis:
|
||||||
readtimeout: 10ms
|
readtimeout: 10ms
|
||||||
writetimeout: 10ms
|
writetimeout: 10ms
|
||||||
validation:
|
validation:
|
||||||
manifests:
|
imageindexes:
|
||||||
imageindex:
|
platformsexist: none
|
||||||
images:
|
|
||||||
exist: false
|
|
||||||
`
|
`
|
||||||
|
|
||||||
// inmemoryConfigYamlV0_1 is a Version 0.1 yaml document specifying an inmemory
|
// inmemoryConfigYamlV0_1 is a Version 0.1 yaml document specifying an inmemory
|
||||||
|
@ -271,10 +259,8 @@ http:
|
||||||
headers:
|
headers:
|
||||||
X-Content-Type-Options: [nosniff]
|
X-Content-Type-Options: [nosniff]
|
||||||
validation:
|
validation:
|
||||||
manifests:
|
imageindexes:
|
||||||
imageindex:
|
platformsexist: none
|
||||||
images:
|
|
||||||
exist: false
|
|
||||||
`
|
`
|
||||||
|
|
||||||
type ConfigSuite struct {
|
type ConfigSuite struct {
|
||||||
|
@ -367,7 +353,7 @@ func (suite *ConfigSuite) TestParseIncomplete(c *check.C) {
|
||||||
IdleTimeout time.Duration `yaml:"idletimeout,omitempty"`
|
IdleTimeout time.Duration `yaml:"idletimeout,omitempty"`
|
||||||
} `yaml:"pool,omitempty"`
|
} `yaml:"pool,omitempty"`
|
||||||
}{}
|
}{}
|
||||||
suite.expectedConfig.Validation.Manifests.ImageIndex.Images.Exist = nil
|
suite.expectedConfig.Validation.ImageIndexes.PlatformsExist = ""
|
||||||
|
|
||||||
// Note: this also tests that REGISTRY_STORAGE and
|
// Note: this also tests that REGISTRY_STORAGE and
|
||||||
// REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY can be used together
|
// REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY can be used together
|
||||||
|
@ -667,6 +653,7 @@ func copyConfig(config Configuration) *Configuration {
|
||||||
Enabled: config.Validation.Enabled,
|
Enabled: config.Validation.Enabled,
|
||||||
Disabled: config.Validation.Disabled,
|
Disabled: config.Validation.Disabled,
|
||||||
Manifests: config.Validation.Manifests,
|
Manifests: config.Validation.Manifests,
|
||||||
|
ImageIndexes: config.Validation.ImageIndexes,
|
||||||
}
|
}
|
||||||
|
|
||||||
return configCopy
|
return configCopy
|
||||||
|
|
|
@ -1247,16 +1247,16 @@ features. Each subsection defines such a feature with configurable behavior.
|
||||||
|
|
||||||
## `validation`
|
## `validation`
|
||||||
|
|
||||||
```none
|
```yaml
|
||||||
validation:
|
validation:
|
||||||
manifests:
|
disabled: false
|
||||||
urls:
|
|
||||||
allow:
|
|
||||||
- ^https?://([^/]+\.)*example\.com/
|
|
||||||
deny:
|
|
||||||
- ^https?://www\.example\.com/
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use these settings to configure what validation the registry performs on content.
|
||||||
|
|
||||||
|
Validation is performed when content is uploaded to the registry. Changing these
|
||||||
|
settings will not validate content that has already been accepting into the registry.
|
||||||
|
|
||||||
### `disabled`
|
### `disabled`
|
||||||
|
|
||||||
The `disabled` flag disables the other options in the `validation`
|
The `disabled` flag disables the other options in the `validation`
|
||||||
|
@ -1269,6 +1269,16 @@ Use the `manifests` subsection to configure validation of manifests. If
|
||||||
|
|
||||||
#### `urls`
|
#### `urls`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
validation:
|
||||||
|
manifests:
|
||||||
|
urls:
|
||||||
|
allow:
|
||||||
|
- ^https?://([^/]+\.)*example\.com/
|
||||||
|
deny:
|
||||||
|
- ^https?://www\.example\.com/
|
||||||
|
```
|
||||||
|
|
||||||
The `allow` and `deny` options are each a list of
|
The `allow` and `deny` options are each a list of
|
||||||
[regular expressions](https://pkg.go.dev/regexp/syntax) that restrict the URLs in
|
[regular expressions](https://pkg.go.dev/regexp/syntax) that restrict the URLs in
|
||||||
pushed manifests.
|
pushed manifests.
|
||||||
|
@ -1282,27 +1292,47 @@ one of the `allow` regular expressions **and** one of the following holds:
|
||||||
2. `deny` is set but no URLs within the manifest match any of the `deny` regular
|
2. `deny` is set but no URLs within the manifest match any of the `deny` regular
|
||||||
expressions.
|
expressions.
|
||||||
|
|
||||||
#### `imageindex`
|
### `imageindexes`
|
||||||
|
|
||||||
##### `images`
|
validation:
|
||||||
|
imageindexes:
|
||||||
|
platformsexist: [All|None|Selected]
|
||||||
|
selectedplatforms:
|
||||||
|
- os: linux
|
||||||
|
architecture: amd64
|
||||||
|
|
||||||
Set `exist` to false to disable validation that images exist when an image
|
Use these settings to configure what validation the registry performs on image
|
||||||
index manifest is uploaded.
|
index manifests uploaded to the registry.
|
||||||
|
|
||||||
Set `platforms` to configure the set of platforms to validate the existence of.
|
#### `platformsexist`
|
||||||
If a platform is included in this list and in the images contained within an index,
|
|
||||||
the registry will validate that it exists in the registry. The registry will not
|
|
||||||
validate the existence of other platform images in the index.
|
|
||||||
|
|
||||||
This parameter does not validate that the platforms are included in the index,
|
Set `platformexist` to `all` (the default) to validate all platform images exist.
|
||||||
if an image index is missing one or more platform images from this array it may
|
The registry will validate that the images referenced by the index exist in the
|
||||||
still be accepted by the registry.
|
registry before accepting the image index.
|
||||||
|
|
||||||
|
Set `platformsexist` to `none` to disable all validation that images exist when an
|
||||||
|
image index manifest is uploaded. This allows image lists to be uploaded to the
|
||||||
|
registry without their associated images.
|
||||||
|
|
||||||
|
Set `platformsexist` to `selected` to selectively validate the existence of platforms
|
||||||
|
within image index manifests.
|
||||||
|
|
||||||
|
#### `selectedplatforms`
|
||||||
|
|
||||||
|
When `platformsexist` is set to `selected`, set `selectedplatforms` to an array of
|
||||||
|
platforms to validate. If a platform is included in this the array and in the images
|
||||||
|
contained within an index, the registry will validate that the platform specific image
|
||||||
|
exists in the registry before accepting the index. The registry will not validate the
|
||||||
|
existence of platform specific images in the index that do not appear in the
|
||||||
|
`selectedplatforms` array.
|
||||||
|
|
||||||
|
This parameter does not validate that the configured platforms are included in every
|
||||||
|
index. If an image index does not include one of the platform specific images configured
|
||||||
|
in the `selectedplatforms` array, it may still be accepted by the registry.
|
||||||
|
|
||||||
Each platform is a map with two keys, `os` and `architecture`, as defined in the
|
Each platform is a map with two keys, `os` and `architecture`, as defined in the
|
||||||
[OCI Image Index specification](https://github.com/opencontainers/image-spec/blob/main/image-index.md#image-index-property-descriptions).
|
[OCI Image Index specification](https://github.com/opencontainers/image-spec/blob/main/image-index.md#image-index-property-descriptions).
|
||||||
|
|
||||||
If `platforms` is an empty array, all images in the index must exist.
|
|
||||||
|
|
||||||
## Example: Development configuration
|
## Example: Development configuration
|
||||||
|
|
||||||
You can use this simple example for local development:
|
You can use this simple example for local development:
|
||||||
|
|
|
@ -258,15 +258,17 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
||||||
options = append(options, storage.ManifestURLsDenyRegexp(re))
|
options = append(options, storage.ManifestURLsDenyRegexp(re))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If unset, default to true
|
// Any option except "none" enables the validation
|
||||||
if config.Validation.Manifests.ImageIndex.Images.Exist == nil ||
|
if config.Validation.ImageIndexes.PlatformsExist != "none" {
|
||||||
*config.Validation.Manifests.ImageIndex.Images.Exist {
|
|
||||||
options = append(options, storage.EnableValidateImageIndexImagesExist)
|
options = append(options, storage.EnableValidateImageIndexImagesExist)
|
||||||
}
|
}
|
||||||
for _, platform := range config.Validation.Manifests.ImageIndex.Images.Platforms {
|
// If we are verifying selected image platforms, add those platforms to the options
|
||||||
|
if config.Validation.ImageIndexes.PlatformsExist == "selected" {
|
||||||
|
for _, platform := range config.Validation.ImageIndexes.SelectedPlatforms {
|
||||||
options = append(options, storage.AddValidateImageIndexImagesExistPlatform(platform.Architecture, platform.OS))
|
options = append(options, storage.AddValidateImageIndexImagesExistPlatform(platform.Architecture, platform.OS))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// configure storage caches
|
// configure storage caches
|
||||||
if cc, ok := config.Storage["cache"]; ok {
|
if cc, ok := config.Storage["cache"]; ok {
|
||||||
|
|
Loading…
Reference in a new issue