Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 10 additions & 37 deletions docs/dev/alternative_release_image_sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,33 @@

## release-image content vs release-image source

`release-image` content is what operators get installed and what version of each operator (i.e. the container image) gets installed to the cluster. While, `release-image` source is **where** the `release-image` content gets pulled.
`release-image` **content** - which operators get installed to the cluster & which version/container image of each operator
`release-image` **source** - where `release-image` content gets pulled from

Currently the installer controls **both** the `release-image` content and the `release-image` source using the embedded release-image location or the `OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE` env, but to allow users to use a release-image from their private registry (change the `release-image` source), but keep the `release-image` content identical to one vetted by OpenShift, the installer needs to allow specifying source separate from the content.
The installer controls *both* the `release-image` content and source using the embedded release-image location or the `OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE` env. Users may also use a release-image from a private registry (change the `release-image` source), but keep the `release-image` content identical to one vetted by OpenShift.

## Controlling the content

The content of the `release-image`, i.e. the digest, continues to be controlled by the embedded release-image location or the `OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE` env.

## Controlling the source

The installer allows the users to specify the sources for the release-image repository and the other repositories referenced in the release-image through the InstallConfig.
The installer allows the users to specify sources for the release-image repository and other repositories referenced in the release-image through the InstallConfig.

## Details

The design is based on the assumption that all flows of using multiple sources/repositories for the release-image originate from user's using the `oc adm release mirror` command to create those sources/repositories.
The design is based on the assumption that all flows of using multiple sources/repositories for the release-image originate with the `oc adm release mirror` command to create those sources/repositories.

## InstallConfig

```go
type InstallConfig struct {
///

// ImageContentSources is the list of sources/repositories that can be used to pull the same content.
// ImageContentSources lists sources/repositories for the release-image content.
// No two ImageContentSource in the list can include the same repository. Each ImageContentSource must be a disjoint set from the rest.
ImageContentSources []ImageContentSource `json:"imageContentSources"`

///
}

// ImageContentSource defines a list of sources/repositories that can be used to pull a content.
// ImageContentSource defines a list of sources/repositories that can be used to pull content.
type ImageContentSource struct {
Sources []string `json:"Sources"`
}
Expand All @@ -53,19 +50,7 @@ imageContentSources:

If a list of `ImageContentSources` is specified, the installer configures the [RepositoryDigestMirrors][repository-digest-mirrors] for each `ImageContentSource`.

If the `install-config.yaml` provided by the user is:

```yaml
...
imageContentSources:
- sources:
- local.registry.com/ocp/release-x.y
- q.io/ocp/release-x.y
- q.io/openshift/x.y
...
```

The `ImageContentSourcePolicy` object would look like:
Using the same `install-config.yaml` from above, the `ImageContentSourcePolicy` object would look like:

```yaml
...
Expand All @@ -85,19 +70,7 @@ The release-image location that is propagated to the bootstrap node and the clus

If a list of `ImageContentSources` is specified, the [Registries][registry-containers-registries-conf] will be configured to have each source be a mirror for another.

For example,

If the `install-config.yaml` provided by the user is:

```yaml
...
imageContentSources:
- sources:
- local.registry.com/ocp/release-x.y
- q.io/ocp/release-x.y
- q.io/openshift/x.y
...
```
For example, our `install-config.yaml` will result in:

```toml
[[registry]]
Expand Down Expand Up @@ -142,7 +115,7 @@ location = "q.io/openshift/x.y"

### oc adm release mirror

The `release mirror` mirrors the a release-image and all other images referenced in the release-image to another repository and then provides user's details of setting up the `install-config.yaml` for the user.
The `release mirror` mirrors the release-image and all other images referenced in the release-image to another repository and then provides details for setting up the `install-config.yaml`.

The output would look like:

Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/manifests/imagesourcepolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (*ImageContentSourcePolicy) Dependencies() []asset.Asset {
}
}

// Generate generates the Proxy config and its CRD.
// Generate generates the ImageContentSourcePolicy config and its CRD.
func (p *ImageContentSourcePolicy) Generate(dependencies asset.Parents) error {
installconfig := &installconfig.InstallConfig{}
dependencies.Get(installconfig)
Expand Down
4 changes: 2 additions & 2 deletions pkg/types/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type InstallConfig struct {
// +optional
Proxy *Proxy `json:"proxy,omitempty"`

// ImageContentSources is the lists of sources/repositories that can be used to pull the same content.
// ImageContentSources lists sources/repositories for the release-image content.
// No two ImageContentSource in the list can include the same repository. Each ImageContentSource must be a disjoint set from the rest.
ImageContentSources []ImageContentSource `json:"imageContentSources,omitempty"`
}
Expand Down Expand Up @@ -216,7 +216,7 @@ type Proxy struct {
NoProxy string `json:"noProxy,omitempty"`
}

// ImageContentSource defines a list of sources/repositories that can be used to pull a content.
// ImageContentSource defines a list of sources/repositories that can be used to pull content.
type ImageContentSource struct {
Sources []string `json:"sources,omitempty"`
}
4 changes: 2 additions & 2 deletions pkg/types/validation/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ func validateImageContentSources(groups []types.ImageContentSource, fldPath *fie
continue
}
if !dockerref.IsNameOnly(ref) {
allErrs = append(allErrs, field.Invalid(f.Index(sidx), source, "must be repository not a reference"))
allErrs = append(allErrs, field.Invalid(f.Index(sidx), source, "must be repository--not reference"))
continue
}
}
Expand All @@ -296,7 +296,7 @@ func validateImageContentSources(groups []types.ImageContentSource, fldPath *fie
jset := sets.NewString(groups[j].Sources...)
intset := iset.Intersection(jset)
if intset.Len() != 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Index(i), groups[i], fmt.Sprintf("Overlapping sources other ImageContentSources is not allowed, overlapping sources found with %s: %s", fldPath.Index(j).String(), intset.List())))
allErrs = append(allErrs, field.Invalid(fldPath.Index(i), groups[i], fmt.Sprintf("all sources in ImageContentSources must be unique, overlapping sources found with %s: %s", fldPath.Index(j).String(), intset.List())))
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/types/validation/installconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ func TestValidateInstallConfig(t *testing.T) {
}}
return c
}(),
expectedError: `^imageContentSources\[0\].source\[0\]: Invalid value: "quay.io/ocp/release-x.y@sha256:397c867cc10bcc90cf05ae9b71dd3de6000535e27cb6c704d9f503879202582c": must be repository not a reference$`,
expectedError: `^imageContentSources\[0\].source\[0\]: Invalid value: "quay.io/ocp/release-x.y@sha256:397c867cc10bcc90cf05ae9b71dd3de6000535e27cb6c704d9f503879202582c": must be repository--not reference$`,
},
{
name: "release image source is not repository but reference by tag",
Expand All @@ -561,7 +561,7 @@ func TestValidateInstallConfig(t *testing.T) {
}}
return c
}(),
expectedError: `^imageContentSources\[0\].source\[0\]: Invalid value: "quay.io/ocp/release-x.y:latest": must be repository not a reference$`,
expectedError: `^imageContentSources\[0\].source\[0\]: Invalid value: "quay.io/ocp/release-x.y:latest": must be repository--not reference$`,
},
{
name: "valid release image source",
Expand All @@ -584,7 +584,7 @@ func TestValidateInstallConfig(t *testing.T) {
}}
return c
}(),
expectedError: `^imageContentSources\[0\]: Invalid value: types.ImageContentSource{Sources:\[\]string{"quay.io\/ocp\/release-x.y", "mirror.test\/ocp\/release-x.y"}}: Overlapping sources other ImageContentSources is not allowed, overlapping sources found with imageContentSources\[1\]: \[mirror.test\/ocp\/release-x.y\]$`,
expectedError: `^imageContentSources\[0\]: Invalid value: types.ImageContentSource{Sources:\[\]string{"quay.io\/ocp\/release-x.y", "mirror.test\/ocp\/release-x.y"}}: all sources in ImageContentSources must be unique, overlapping sources found with imageContentSources\[1\]: \[mirror.test\/ocp\/release-x.y\]$`,
},
}
for _, tc := range cases {
Expand Down