Skip to content

Commit

Permalink
Merge pull request #1008 from jacobweinstock/iso-mounting
Browse files Browse the repository at this point in the history
Add ISO mounting to Workflow boot options:

## Description

<!--- Please describe what this PR is going to change -->
Add ISO mounting capabilities to Workflow (spec) boot options. This is similar to the netboot option but with a virtual media mount and CDROM as the next boot device. This refactors the Workflow spec to be able to handle both network boot and iso booting.

 Current Workflow spec example:
 
```yaml
apiVersion: tinkerbell.org/v1alpha1
kind: Workflow
metadata:
  name: example1
  namespace: tink-system
spec:
  hardwareMap:
    device_1: 01:02:03:04:05:06
  templateRef: myTemplate
  hardwareRef: example1
  bootOptions:
    toggleAllowNetboot: true
    oneTimeNetboot: true
```

New Workflow spec example for network booting a machine:
 
```yaml
apiVersion: tinkerbell.org/v1alpha1
kind: Workflow
metadata:
  name: example1
  namespace: tink-system
spec:
  hardwareMap:
    device_1: 01:02:03:04:05:06
  templateRef: myTemplate
  hardwareRef: example1
  bootOptions:
    toggleAllowNetboot: true
    bootMode: netboot
```

New Workflow spec example for ISO booting a machine:
 
```yaml
apiVersion: tinkerbell.org/v1alpha1
kind: Workflow
metadata:
  name: example1
  namespace: tink-system
spec:
  hardwareMap:
    device_1: 01:02:03:04:05:06
  templateRef: myTemplate
  hardwareRef: example1
  bootOptions:
    toggleAllowNetboot: true
    bootMode: iso
    isoURL: http://192.168.2.113:7171/ipxe/ipxe.iso
```

## Why is this needed

<!--- Link to issue you have raised -->

Fixes: #

## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->


## How are existing users impacted? What migration steps/scripts do we need?

<!--- Fixes a bug, unblocks installation, removes a component of the stack etc -->
<!--- Requires a DB migration script, etc. -->

Upgrade:

1. Update the workflow CRD
   ```bash
   kubectl replace -f https://raw.githubusercontent.com/tinkerbell/tink/refs/heads/main/config/crd/bases/tinkerbell.org_workflows.yaml
   ```
2. Update the tink controller Role
   ```bash
   kubectl replace -f https://raw.githubusercontent.com/tinkerbell/tink/refs/heads/main/config/manager-rbac/role.yaml -n tink-system
   ```
3. Update tink controller and tink server images
   ```bash
   kubectl set image -n tink-system deployment/tink-controller tink-controller=quay.io/tinkerbell/tink-controller:latest
   kubectl set image -n tink-system deployment/tink-server server=quay.io/tinkerbell/tink-server:latest
   ```


## Checklist:

I have:

- [ ] updated the documentation and/or roadmap (if required)
- [ ] added unit or e2e tests
- [ ] provided instructions on how to upgrade
  • Loading branch information
jacobweinstock authored Oct 14, 2024
2 parents 2fb5e40 + 8997356 commit 8c7a9c8
Show file tree
Hide file tree
Showing 19 changed files with 1,353 additions and 874 deletions.
46 changes: 32 additions & 14 deletions api/v1alpha1/workflow_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ type (
WorkflowState string
WorkflowConditionType string
TemplateRendering string
BootMode string
)

const (
WorkflowStateWaiting = WorkflowState("STATE_WAITING")
WorkflowStatePending = WorkflowState("STATE_PENDING")
WorkflowStateRunning = WorkflowState("STATE_RUNNING")
WorkflowStateSuccess = WorkflowState("STATE_SUCCESS")
WorkflowStateFailed = WorkflowState("STATE_FAILED")
WorkflowStateTimeout = WorkflowState("STATE_TIMEOUT")
WorkflowStatePreparing = WorkflowState("STATE_PREPARING")
WorkflowStatePending = WorkflowState("STATE_PENDING")
WorkflowStateRunning = WorkflowState("STATE_RUNNING")
WorkflowStatePost = WorkflowState("STATE_POST")
WorkflowStateSuccess = WorkflowState("STATE_SUCCESS")
WorkflowStateFailed = WorkflowState("STATE_FAILED")
WorkflowStateTimeout = WorkflowState("STATE_TIMEOUT")

NetbootJobFailed WorkflowConditionType = "NetbootJobFailed"
NetbootJobComplete WorkflowConditionType = "NetbootJobComplete"
Expand All @@ -34,6 +36,9 @@ const (

TemplateRenderingSuccessful TemplateRendering = "successful"
TemplateRenderingFailed TemplateRendering = "failed"

BootModeNetboot BootMode = "netboot"
BootModeISO BootMode = "iso"
)

// +kubebuilder:subresource:status
Expand Down Expand Up @@ -86,18 +91,31 @@ type BootOptions struct {
// A HardwareRef must be provided.
// +optional
ToggleAllowNetboot bool `json:"toggleAllowNetboot,omitempty"`
// OneTimeNetboot indicates whether the controller should create a job.bmc.tinkerbell.org object for getting the associated hardware
// into a netbooting state.

// ISOURL is the URL of the ISO that will be one-time booted. When this field is set, the controller will create a job.bmc.tinkerbell.org object
// for getting the associated hardware into a CDROM booting state.
// A HardwareRef that contains a spec.BmcRef must be provided.
// +optional
OneTimeNetboot bool `json:"oneTimeNetboot,omitempty"`
// +kubebuilder:validation:Format=url
ISOURL string `json:"isoURL,omitempty"`

// BootMode is the type of booting that will be done.
// +optional
// +kubebuilder:validation:Enum=netboot;iso
BootMode BootMode `json:"bootMode,omitempty"`
}

// BootOptionsStatus holds the state of any boot options.
type BootOptionsStatus struct {
// OneTimeNetboot holds the state of a specific job.bmc.tinkerbell.org object created.
// Only used when BootOptions.OneTimeNetboot is true.
OneTimeNetboot OneTimeNetbootStatus `json:"netbootJob,omitempty"`
// AllowNetboot holds the state of the the controller's interactions with the allowPXE field in a Hardware object.
AllowNetboot AllowNetbootStatus `json:"allowNetboot,omitempty"`
// Jobs holds the state of any job.bmc.tinkerbell.org objects created.
Jobs map[string]JobStatus `json:"jobs,omitempty"`
}

type AllowNetbootStatus struct {
ToggledTrue bool `json:"toggledTrue,omitempty"`
ToggledFalse bool `json:"toggledFalse,omitempty"`
}

// WorkflowStatus defines the observed state of a Workflow.
Expand Down Expand Up @@ -130,8 +148,8 @@ type WorkflowStatus struct {
Conditions []WorkflowCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"`
}

// OneTimeNetbootStatus holds the state of a specific job.bmc.tinkerbell.org object created.
type OneTimeNetbootStatus struct {
// JobStatus holds the state of a specific job.bmc.tinkerbell.org object created.
type JobStatus struct {
// UID is the UID of the job.bmc.tinkerbell.org object associated with this workflow.
// This is used to uniquely identify the job.bmc.tinkerbell.org object, as
// all objects for a specific Hardware/Machine.bmc.tinkerbell.org are created with the same name.
Expand Down
56 changes: 39 additions & 17 deletions api/v1alpha1/zz_generated.deepcopy.go

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

27 changes: 21 additions & 6 deletions cmd/tink-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/spf13/viper"
"github.com/tinkerbell/tink/internal/deprecated/controller"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -27,6 +28,7 @@ type Config struct {
MetricsAddr string
ProbeAddr string
EnableLeaderElection bool
LogLevel int
}

func (c *Config) AddFlags(fs *pflag.FlagSet) {
Expand All @@ -40,6 +42,7 @@ func (c *Config) AddFlags(fs *pflag.FlagSet) {
fs.BoolVar(&c.EnableLeaderElection, "leader-elect", false,
"Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.")
fs.IntVar(&c.LogLevel, "log-level", 0, "Log level (0: info, 1: debug)")
}

func main() {
Expand All @@ -52,22 +55,34 @@ func main() {
func NewRootCommand() *cobra.Command {
var config Config

zlog, err := zap.NewProduction()
if err != nil {
panic(err)
}
logger := zapr.NewLogger(zlog).WithName("github.com/tinkerbell/tink")

cmd := &cobra.Command{
Use: "tink-controller",
PreRunE: func(cmd *cobra.Command, _ []string) error {
zlog, err := zap.NewProduction()
if err != nil {
panic(err)
}
logger := zapr.NewLogger(zlog).WithName("github.com/tinkerbell/tink")
viper, err := createViper(logger)
if err != nil {
return fmt.Errorf("config init: %w", err)
}
return applyViper(viper, cmd)
},
RunE: func(cmd *cobra.Command, _ []string) error {
zc := zap.NewProductionConfig()
switch config.LogLevel {
case 1:
zc.Level = zap.NewAtomicLevelAt(zapcore.Level(-1))
default:
zc.Level = zap.NewAtomicLevelAt(zapcore.Level(0))
}
zlog, err := zc.Build()
if err != nil {
panic(err)
}

logger := zapr.NewLogger(zlog).WithName("github.com/tinkerbell/tink")
logger.Info("Starting controller version " + version)

ccfg := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
Expand Down
60 changes: 38 additions & 22 deletions config/crd/bases/tinkerbell.org_workflows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,19 @@ spec:
bootOptions:
description: BootOptions are options that control the booting of Hardware.
properties:
oneTimeNetboot:
bootMode:
description: BootMode is the type of booting that will be done.
enum:
- netboot
- iso
type: string
isoURL:
description: |-
OneTimeNetboot indicates whether the controller should create a job.bmc.tinkerbell.org object for getting the associated hardware
into a netbooting state.
ISOURL is the URL of the ISO that will be one-time booted. When this field is set, the controller will create a job.bmc.tinkerbell.org object

Check warning on line 69 in config/crd/bases/tinkerbell.org_workflows.yaml

View workflow job for this annotation

GitHub Actions / Verify

[line-length] line too long (165 > 160 characters)
for getting the associated hardware into a CDROM booting state.
A HardwareRef that contains a spec.BmcRef must be provided.
type: boolean
format: url
type: string
toggleAllowNetboot:
description: |-
ToggleAllowNetboot indicates whether the controller should toggle the field in the associated hardware for allowing PXE booting.
Expand All @@ -89,27 +96,36 @@ spec:
bootOptions:
description: BootOptions holds the state of any boot options.
properties:
netbootJob:
description: |-
OneTimeNetboot holds the state of a specific job.bmc.tinkerbell.org object created.
Only used when BootOptions.OneTimeNetboot is true.
allowNetboot:
description: AllowNetboot holds the state of the the controller's interactions with the allowPXE field in a Hardware object.
properties:
complete:
description: Complete indicates whether the created job.bmc.tinkerbell.org has reported its conditions as complete.
toggledFalse:
type: boolean
existingJobDeleted:
description: |-
ExistingJobDeleted indicates whether any existing job.bmc.tinkerbell.org was deleted.
The name of each job.bmc.tinkerbell.org object created by the controller is the same, so only one can exist at a time.
Using the same name was chosen so that there is only ever 1 job.bmc.tinkerbell.org per Hardware/Machine.bmc.tinkerbell.org.
This makes clean up easier and we dont just orphan jobs every time.
toggledTrue:
type: boolean
uid:
description: |-
UID is the UID of the job.bmc.tinkerbell.org object associated with this workflow.
This is used to uniquely identify the job.bmc.tinkerbell.org object, as
all objects for a specific Hardware/Machine.bmc.tinkerbell.org are created with the same name.
type: string
type: object
jobs:
additionalProperties:
description: JobStatus holds the state of a specific job.bmc.tinkerbell.org object created.
properties:
complete:
description: Complete indicates whether the created job.bmc.tinkerbell.org has reported its conditions as complete.
type: boolean
existingJobDeleted:
description: |-
ExistingJobDeleted indicates whether any existing job.bmc.tinkerbell.org was deleted.
The name of each job.bmc.tinkerbell.org object created by the controller is the same, so only one can exist at a time.
Using the same name was chosen so that there is only ever 1 job.bmc.tinkerbell.org per Hardware/Machine.bmc.tinkerbell.org.
This makes clean up easier and we dont just orphan jobs every time.
type: boolean
uid:
description: |-
UID is the UID of the job.bmc.tinkerbell.org object associated with this workflow.
This is used to uniquely identify the job.bmc.tinkerbell.org object, as
all objects for a specific Hardware/Machine.bmc.tinkerbell.org are created with the same name.
type: string
type: object
description: Jobs holds the state of any job.bmc.tinkerbell.org objects created.
type: object
type: object
conditions:
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ toolchain go1.22.2
require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/avast/retry-go v3.0.0+incompatible
github.com/cenkalti/backoff/v4 v4.3.0
github.com/distribution/reference v0.6.0
github.com/docker/docker v27.3.1+incompatible
github.com/equinix-labs/otel-init-go v0.0.9
Expand Down Expand Up @@ -36,7 +37,6 @@ require (
k8s.io/api v0.31.1
k8s.io/apimachinery v0.31.1
k8s.io/client-go v0.31.1
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8
knative.dev/pkg v0.0.0-20240917091217-aaab500c26c4
sigs.k8s.io/controller-runtime v0.19.0
sigs.k8s.io/yaml v1.4.0
Expand All @@ -48,7 +48,6 @@ require (
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
Expand Down Expand Up @@ -134,6 +133,7 @@ require (
k8s.io/apiextensions-apiserver v0.31.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8 // indirect
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)
Loading

0 comments on commit 8c7a9c8

Please sign in to comment.