Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build-273 Volumes support to Build Strategies #1035

Merged
merged 1 commit into from
May 11, 2022
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
4 changes: 4 additions & 0 deletions deploy/200-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ rules:
resources: ['secrets']
verbs: ['get', 'list', 'watch']

- apiGroups: ['']
resources: ['configmaps']
verbs: ['list']

- apiGroups: ['']
resources: ['serviceaccounts']
verbs: ['get', 'list', 'watch', 'create', 'update', 'delete']
5,675 changes: 5,116 additions & 559 deletions deploy/crds/shipwright.io_buildruns.yaml

Large diffs are not rendered by default.

1,479 changes: 1,479 additions & 0 deletions deploy/crds/shipwright.io_builds.yaml

Large diffs are not rendered by default.

1,480 changes: 1,480 additions & 0 deletions deploy/crds/shipwright.io_buildstrategies.yaml

Large diffs are not rendered by default.

1,480 changes: 1,480 additions & 0 deletions deploy/crds/shipwright.io_clusterbuildstrategies.yaml

Large diffs are not rendered by default.

31 changes: 31 additions & 0 deletions docs/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ SPDX-License-Identifier: Apache-2.0
- [Defining the Builder or Dockerfile](#defining-the-builder-or-dockerfile)
- [Defining the Output](#defining-the-output)
- [Defining Retention Parameters](#defining-retention-parameters)
- [Defining Volumes](#defining-volumes)
- [BuildRun deletion](#BuildRun-deletion)

## Overview
Expand Down Expand Up @@ -571,6 +572,36 @@ An example of a user using both TTL and Limit retention fields. In case of such

**NOTE**: When changes are made to `retention.failedLimit` and `retention.succeededLimit` values, they come into effect as soon as the build is applied, thereby enforcing the new limits. On the other hand, changing the `retention.ttlAfterFailed` and `retention.ttlAfterSucceeded` values will only affect new buildruns. Old buildruns will adhere to the old TTL retention values. In case TTL values are defined in buildrun specifications as well as build specifications, priority will be given to the values defined in the buildrun specifications.

### Defining Volumes

`Builds` can declare `volumes`. They must override `volumes` defined by the according `BuildStrategy`. If a `volume`
is not `overridable` then the `BuildRun` will eventually fail.

`Volumes` follow the declaration of [Pod Volumes](https://kubernetes.io/docs/concepts/storage/volumes/), so
all the usual `volumeSource` types are supported.

Here is an example of `Build` object that overrides `volumes`:

```yaml
apiVersion: shipwright.io/v1alpha1
kind: Build
metadata:
name: build-name
spec:
source:
url: https://github.com/example/url
strategy:
name: buildah
kind: ClusterBuildStrategy
dockerfile: Dockerfile
output:
image: registry/namespace/image:latest
volumes:
- name: volume-name
configMap:
name: test-config
```

### Sources

Sources represent remote artifacts, as in external entities added to the build context before the actual Build starts. Therefore, you may employ `.spec.sources` to download artifacts from external repositories.
Expand Down
28 changes: 28 additions & 0 deletions docs/buildrun.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ SPDX-License-Identifier: Apache-2.0
- [Defining ParamValues](#defining-paramvalues)
- [Defining the ServiceAccount](#defining-the-serviceaccount)
- [Defining Retention Parameters](#defining-retention-parameters)
- [Defining Volumes](#defining-volumes)
- [Canceling a `BuildRun`](#canceling-a-buildrun)
- [Automatic `BuildRun` deletion](#automatic-buildrun-deletion)
- [Specifying Environment Variables](#specifying-environment-variables)
Expand Down Expand Up @@ -194,6 +195,33 @@ spec:

**NOTE** In case TTL values are defined in buildrun specifications as well as build specifications, priority will be given to the values defined in the buildrun specifications.

### Defining Volumes

`BuildRuns` can declare `volumes`. They must override `volumes` defined by the according `BuildStrategy`. If a `volume`
is not `overridable` then the `BuildRun` will eventually fail.

In case `Build` and `BuildRun` that refers to this `Build` override the same `volume`, one that is defined in the `BuildRun`
is the one used eventually.

`Volumes` follow the declaration of [Pod Volumes](https://kubernetes.io/docs/concepts/storage/volumes/), so
all the usual `volumeSource` types are supported.

Here is an example of `BuildRun` object that overrides `volumes`:

```yaml
apiVersion: shipwright.io/v1alpha1
kind: BuildRun
metadata:
name: buildrun-name
spec:
buildRef:
name: build-name
volumes:
- name: volume-name
configMap:
name: test-config
```

## Canceling a `BuildRun`

To cancel a `BuildRun` that's currently executing, update its status to mark it as canceled.
Expand Down
43 changes: 38 additions & 5 deletions docs/buildstrategies.md
Original file line number Diff line number Diff line change
Expand Up @@ -881,9 +881,42 @@ A Kubernetes administrator can further restrict the usage of annotations by usin

## Volumes and VolumeMounts

Build steps can declare a `volumeMount`, which allows data in the provided path to be shared across build steps.
When a `volumeMount` is declared, Shipwright will create an `emptyDir` volume with the corresponding name.
Build steps whose volume mounts share the same name will share the same underlying `emtpyDir` volume.
Build Strategies can declare `volumes`. These `volumes` can be referred to by the build steps using `volumeMount`.
Volumes in Build Strategy follow the declaration of [Pod Volumes](https://kubernetes.io/docs/concepts/storage/volumes/), so
all the usual `volumeSource` types are supported.

In a future release, build strategy authors will be able to use other volume types for the volume mounts.
When this feature is introduced, the volume and volume type will need to be explicitly declared.
Volumes can be overridden by `Build`s and `BuildRun`s, so Build Strategies' volumes support an `overridable` flag, which
is a boolean, and is `false` by default. In case volume is not overridable, `Build` or `BuildRun` that tries to override it,
will fail.

Build steps can declare a `volumeMount`, which allows them to access volumes defined by `BuildStrategy`, `Build` or `BuildRun`.

Here is an example of `BuildStrategy` object that defines `volumes` and `volumeMount`s:
```
apiVersion: shipwright.io/v1alpha1
kind: BuildStrategy
metadata:
name: buildah
spec:
buildSteps:
- name: build
image: quay.io/containers/buildah:v1.23.1
workingDir: $(params.shp-source-root)
command:
- buildah
- bud
- --tls-verify=false
- --layers
- -f
- $(build.dockerfile)
- -t
- $(params.shp-output-image)
- $(params.shp-source-context)
volumeMounts:
- name: varlibcontainers
mountPath: /var/lib/containers
volumes:
- name: varlibcontainers
overridable: true
emptyDir: {}
```
26 changes: 26 additions & 0 deletions pkg/apis/build/v1alpha1/build_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ const (
RemoteRepositoryUnreachable BuildReason = "RemoteRepositoryUnreachable"
// BuildNameInvalid indicates the build name is invalid
BuildNameInvalid BuildReason = "BuildNameInvalid"
// VolumeDoesNotExist indicates that volume referenced by the Build does not exist, therefore Build cannot be run
VolumeDoesNotExist BuildReason = "VolumeDoesNotExist"
// VolumeNotOverridable indicates that volume defined by build is not set as overridable in the strategy
VolumeNotOverridable BuildReason = "VolumeNotOverridable"
// UndefinedVolume indicates that volume defined by build is not found in the strategy
UndefinedVolume BuildReason = "UndefinedVolume"
// AllValidationsSucceeded indicates a Build was successfully validated
AllValidationsSucceeded = "all validations succeeded"
)
Expand Down Expand Up @@ -143,6 +149,26 @@ type BuildSpec struct {
//
// +optional
Retention *BuildRetention `json:"retention,omitempty"`

// Volumes contains volume Overrides of the BuildStrategy volumes in case those are allowed
// to be overridden. Must only contain volumes that exist in the corresponding BuildStrategy
// +optional
Volumes []BuildVolume `json:"volumes,omitempty"`
SaschaSchwarze0 marked this conversation as resolved.
Show resolved Hide resolved
}

// BuildVolume is a volume that will be mounted in build pod during build step
type BuildVolume struct {
// Name of the Build Volume
// +required
Name string `json:"name"`

// Description of the Build Volume
// +optional
Description *string `json:"description,omitempty"`

// Represents the source of a volume to mount
// +required
corev1.VolumeSource `json:",inline"`
}

// StrategyName returns the name of the configured strategy, or 'undefined' in
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/build/v1alpha1/buildrun_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ type BuildRunSpec struct {
// Contains information about retention params
// +optional
Retention *BuildRunRetention `json:"retention,omitempty"`

// Volumes contains volume Overrides of the BuildStrategy volumes in case those are allowed
// to be overridden. Must only contain volumes that exist in the corresponding BuildStrategy
// +optional
Volumes []BuildVolume `json:"volumes,omitempty"`
}

// BuildRunRequestedState defines the buildrun state the user can provide to override whatever is the current state.
Expand Down
19 changes: 17 additions & 2 deletions pkg/apis/build/v1alpha1/buildstrategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ const (

// BuildStrategySpec defines the desired state of BuildStrategy
type BuildStrategySpec struct {
BuildSteps []BuildStep `json:"buildSteps,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
BuildSteps []BuildStep `json:"buildSteps,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
Volumes []BuildStrategyVolume `json:"volumes,omitempty"`
}

// ParameterType indicates the type of a parameter
Expand Down Expand Up @@ -59,6 +60,19 @@ type Parameter struct {
Defaults *[]string `json:"defaults"`
}

// BuildStrategyVolume is a volume that will be mounted in build pod during build step
// of the Build Strategy
type BuildStrategyVolume struct {
SaschaSchwarze0 marked this conversation as resolved.
Show resolved Hide resolved
// Indicates that this Volume can be overridden in a Build or BuildRun.
// Defaults to false
// +optional
Overridable *bool `json:"overridable,omitempty"`

// Inline BuildVolume object, same as Build's Volume
// +required
BuildVolume `json:",inline"`
}

// BuildStep defines a partial step that needs to run in container for building the image.
// If the build step declares a volumeMount, Shipwright will create an emptyDir volume mount for the named volume.
// Build steps which share the same named volume in the volumeMount will share the same underlying emptyDir volume.
Expand Down Expand Up @@ -97,4 +111,5 @@ type BuilderStrategy interface {
GetResourceLabels() map[string]string
GetBuildSteps() []BuildStep
GetParameters() []Parameter
GetVolumes() []BuildStrategyVolume
}
5 changes: 5 additions & 0 deletions pkg/apis/build/v1alpha1/buildstrategy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ func (s BuildStrategy) GetParameters() []Parameter {
return s.Spec.Parameters
}

// GetVolumes returns the volumes defined by the build strategy
func (s BuildStrategy) GetVolumes() []BuildStrategyVolume {
return s.Spec.Volumes
}

func init() {
SchemeBuilder.Register(&BuildStrategy{}, &BuildStrategyList{})
}
5 changes: 5 additions & 0 deletions pkg/apis/build/v1alpha1/clusterbuildstrategy_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ func (s ClusterBuildStrategy) GetParameters() []Parameter {
return s.Spec.Parameters
}

// GetVolumes returns the volumes defined by the build strategy
func (s ClusterBuildStrategy) GetVolumes() []BuildStrategyVolume {
return s.Spec.Volumes
}

func init() {
SchemeBuilder.Register(&ClusterBuildStrategy{}, &ClusterBuildStrategyList{})
}
65 changes: 65 additions & 0 deletions pkg/apis/build/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions pkg/reconciler/buildrun/buildrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,15 @@ func (r *ReconcileBuildRun) Reconcile(ctx context.Context, request reconcile.Req
return reconcile.Result{}, nil
}

// Validate the volumes
valid, reason, message = validate.BuildRunVolumes(strategy.GetVolumes(), buildRun.Spec.Volumes)
if !valid {
if err := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, message, reason); err != nil {
return reconcile.Result{}, err
}
return reconcile.Result{}, nil
}

// Create the TaskRun, this needs to be the last step in this block to be idempotent
generatedTaskRun, err := r.createTaskRun(ctx, svcAccount, strategy, build, buildRun)
if err != nil {
Expand All @@ -292,6 +301,22 @@ func (r *ReconcileBuildRun) Reconcile(ctx context.Context, request reconcile.Req
return reconcile.Result{}, err
}

err = resources.CheckTaskRunVolumesExist(ctx, r.client, generatedTaskRun)
// if resource is not found, fais the build run
if err != nil {
if apierrors.IsNotFound(err) {
if err := resources.UpdateConditionWithFalseStatus(ctx, r.client, buildRun, err.Error(), string(buildv1alpha1.VolumeDoesNotExist)); err != nil {
return reconcile.Result{}, err
}

// end of reconciliation
return reconcile.Result{}, nil
}

// some other error might have happened, return it and reconcile again
return reconcile.Result{}, err
}

ctxlog.Info(ctx, "creating TaskRun from BuildRun", namespace, request.Namespace, name, generatedTaskRun.GenerateName, "BuildRun", buildRun.Name)
if err = r.client.Create(ctx, generatedTaskRun); err != nil {
// system call failure, reconcile again
Expand Down
Loading