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

Add Mkdocs-based Documentation and Automated API Reference Documentation Generation #105

Merged
merged 2 commits into from
Jan 13, 2025
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
23 changes: 23 additions & 0 deletions .github/workflows/publish_docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Publish docs via GitHub Pages
on:
push:
branches: [ main ]

jobs:
build:
name: Deploy docs
runs-on: ubuntu-latest
steps:
- name: Checkout main
uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 'pypy3.9'
- uses: actions/cache@v4
with:
key: ${{ github.ref }}
path: .cache
- name: Deploy docs
uses: afritzler/mkdocs-gh-pages-action@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Files:
test/*
CONTRIBUTING.md
PROJECT
mkdocs.yml
.dockerignore
.golangci.yml
Copyright: 2024 SAP SE or an SAP affiliate company and IronCore contributors
Expand Down
24 changes: 24 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ IMG ?= controller:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.31.0

# Docker image name for the mkdocs based local development setup
IMAGE=ironcore-dev/boot-operator-docs

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
Expand Down Expand Up @@ -171,6 +174,7 @@ ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)
ADDLICENSE ?= $(LOCALBIN)/addlicense
GOIMPORTS ?= $(LOCALBIN)/goimports-$(GOIMPORTS_VERSION)
GEN_CRD_API_REFERENCE_DOCS ?= $(LOCALBIN)/gen-crd-api-reference-docs-$(GEN_CRD_API_REFERENCE_DOCS_VERSION)

## Tool Versions
KUSTOMIZE_VERSION ?= v5.3.0
Expand All @@ -179,6 +183,7 @@ ENVTEST_VERSION ?= latest
GOLANGCI_LINT_VERSION ?= v1.61.0
ADDLICENSE_VERSION ?= v1.1.1
GOIMPORTS_VERSION ?= v0.26.0
GEN_CRD_API_REFERENCE_DOCS_VERSION ?= v0.3.0

.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
Expand All @@ -200,6 +205,16 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})


.PHONY: startdocs
startdocs: ## Start the local mkdocs based development environment.
docker build -t $(IMAGE) -f docs/Dockerfile . --load
docker run -p 8000:8000 -v `pwd`/:/docs $(IMAGE)

.PHONY: cleandocs
cleandocs: ## Remove all local mkdocs Docker images (cleanup).
docker container prune --force --filter "label=project=boot_operator"

.PHONY: addlicense
addlicense: $(ADDLICENSE) ## Download addlicense locally if necessary.
$(ADDLICENSE): $(LOCALBIN)
Expand All @@ -210,6 +225,15 @@ goimports: $(GOIMPORTS) ## Download goimports locally if necessary.
$(GOIMPORTS): $(LOCALBIN)
$(call go-install-tool,$(GOIMPORTS),golang.org/x/tools/cmd/goimports,$(GOIMPORTS_VERSION))

.PHONY: docs
docs: gen-crd-api-reference-docs ## Run go generate to generate API reference documentation.
$(GEN_CRD_API_REFERENCE_DOCS) -api-dir ./api/v1alpha1 -config ./hack/api-reference/config.json -template-dir ./hack/api-reference/template -out-file ./docs/api-reference/api.md

.PHONY: gen-crd-api-reference-docs
gen-crd-api-reference-docs: $(GEN_CRD_API_REFERENCE_DOCS) ## Download gen-crd-api-reference-docs locally if necessary.
$(GEN_CRD_API_REFERENCE_DOCS): $(LOCALBIN)
$(call go-install-tool,$(GEN_CRD_API_REFERENCE_DOCS),github.com/ahmetb/gen-crd-api-reference-docs,$(GEN_CRD_API_REFERENCE_DOCS_VERSION))

# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary (ideally with version)
# $2 - package url which can be installed
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ More information can be found via the [Kubebuilder Documentation](https://book.k
## Roadmap
Looking ahead, the boot-Operator aims to introduce a range of enhancements to further empower Kubernetes-driven infrastructure provisioning:

- Configurable iPXE Scripts: Enable customization of iPXE script templates to accommodate diverse booting requirements.

- Custom Image Registry Support: Dynamically generate URLs for the kernel, initrd, and squashfs images from a specified image registry, facilitating streamlined updates and deployments.

- Expanded Endpoints: Introduce additional endpoints, such as `/ztp` for Zero Touch Provisioning of switches and `/certs` for certificate management, broadening the operator's utility.
Expand Down
7 changes: 7 additions & 0 deletions api/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0

// Package v1alpha1 contains API Schema definitions for the settings.gardener.cloud API group
// +groupName=metal.ironcore.dev
// +kubebuilder:object:generate=true
package v1alpha1
22 changes: 17 additions & 5 deletions api/v1alpha1/httpbootconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,17 @@ import (

// HTTPBootConfigSpec defines the desired state of HTTPBootConfig
type HTTPBootConfigSpec struct {
SystemUUID string `json:"systemUUID,omitempty"`
// SystemUUID is the unique identifier (UUID) of the server.
SystemUUID string `json:"systemUUID,omitempty"`

// IgnitionSecretRef is a reference to the secret containing Ignition configuration.
IgnitionSecretRef *corev1.LocalObjectReference `json:"ignitionSecretRef,omitempty"`
SystemIPs []string `json:"systemIPs,omitempty"`
UKIURL string `json:"ukiURL,omitempty"`

// SystemIPs is a list of IP addresses assigned to the server.
SystemIPs []string `json:"systemIPs,omitempty"`

// UKIURL is the URL where the UKI (Unified Kernel Image) is hosted.
UKIURL string `json:"ukiURL,omitempty"`
}

// HTTPBootConfigStatus defines the observed state of HTTPBootConfig
Expand All @@ -24,9 +31,14 @@ type HTTPBootConfigStatus struct {
type HTTPBootConfigState string

const (
HTTPBootConfigStateReady HTTPBootConfigState = "Ready"
// HTTPBootConfigStateReady indicates that the HTTPBootConfig has been successfully processed, and the next step (e.g., booting the server) can proceed.
HTTPBootConfigStateReady HTTPBootConfigState = "Ready"

// HTTPBootConfigStatePending indicates that the HTTPBootConfig has not been processed yet.
HTTPBootConfigStatePending HTTPBootConfigState = "Pending"
HTTPBootConfigStateError HTTPBootConfigState = "Error"

// HTTPBootConfigStateError indicates that an error occurred while processing the HTTPBootConfig.
HTTPBootConfigStateError HTTPBootConfigState = "Error"
)

// +kubebuilder:object:root=true
Expand Down
43 changes: 31 additions & 12 deletions api/v1alpha1/ipxebootconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,45 @@ import (

// IPXEBootConfigSpec defines the desired state of IPXEBootConfig
type IPXEBootConfigSpec struct {
// Important: Run "make" to regenerate code after modifying this file
SystemUUID string `json:"systemUUID,omitempty"`
SystemIPs []string `json:"systemIPs,omitempty"` // TODO: Add the custom serialization. For now validate at the controller.
// TODO: remove image as this is not needed
Image string `json:"image,omitempty"`
KernelURL string `json:"kernelURL,omitempty"`
InitrdURL string `json:"initrdURL,omitempty"`
// SystemUUID is the unique identifier (UUID) of the server.
SystemUUID string `json:"systemUUID,omitempty"`

// SystemIPs is a list of IP addresses assigned to the server.
SystemIPs []string `json:"systemIPs,omitempty"` // TODO: Implement custom serialization. Currently, validation should occur at the controller.

// Image is deprecated and will be removed.
Image string `json:"image,omitempty"`

// KernelURL is the URL where the kernel of the OS is hosted, eg. the URL to the Kernel layer of the OS OCI image.
KernelURL string `json:"kernelURL,omitempty"`

// InitrdURL is the URL where the Initrd (initial RAM disk) of the OS is hosted, eg. the URL to the Initrd layer of the OS OCI image.
InitrdURL string `json:"initrdURL,omitempty"`

// SquashfsURL is the URL where the Squashfs of the OS is hosted, eg. the URL to the Squashfs layer of the OS OCI image.
SquashfsURL string `json:"squashfsURL,omitempty"`
// TODO: remove later
IPXEServerURL string `json:"ipxeServerURL,omitempty"`
IgnitionSecretRef *corev1.LocalObjectReference `json:"ignitionSecretRef,omitempty"`

// IPXEServerURL is deprecated and will be removed.
IPXEServerURL string `json:"ipxeServerURL,omitempty"`

// IgnitionSecretRef is a reference to the secret containing the Ignition configuration.
IgnitionSecretRef *corev1.LocalObjectReference `json:"ignitionSecretRef,omitempty"`

// IPXEScriptSecretRef is a reference to the secret containing the custom IPXE script.
IPXEScriptSecretRef *corev1.LocalObjectReference `json:"ipxeScriptSecretRef,omitempty"`
}

type IPXEBootConfigState string

const (
IPXEBootConfigStateReady IPXEBootConfigState = "Ready"
// IPXEBootConfigStateReady indicates that the IPXEBootConfig has been successfully processed, and the next step (e.g., booting the server) can proceed.
IPXEBootConfigStateReady IPXEBootConfigState = "Ready"

// IPXEBootConfigStatePending indicates that the IPXEBootConfig has not been processed yet.
IPXEBootConfigStatePending IPXEBootConfigState = "Pending"
IPXEBootConfigStateError IPXEBootConfigState = "Error"

// IPXEBootConfigStateError indicates that an error occurred while processing the IPXEBootConfig.
IPXEBootConfigStateError IPXEBootConfigState = "Error"
)

// IPXEBootConfigStatus defines the observed state of IPXEBootConfig
Expand Down
15 changes: 7 additions & 8 deletions config/samples/httpbootconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ metadata:
app.kubernetes.io/created-by: boot-operator
name: httpbootconfig-sample
spec:
systemUUID: 1234
systemIPs:
- 1.2.3.4
ignitionSecretRef:
name: ignition-sample
kernelURL: "10.0.0.1/ipxe/rootfs.vmlinuz"
initrdURL: "10.0.0.1/ipxe/rootfs.initrd"
squashfsURL: "10.0.0.1/ipxe/root.squashfs"

name: ignition-foo
namespace: default
systemIPs:
- f55b:9d4e:e9c9:5183:f7e8:3012:60ce:497b
- 1001:194a:21fb:53d3:9de1:28f3:97ce:d31d
systemUUID: abcd648-490f-11ea-a6c2-0a94efaabcdrd
ukiURL: http://[feed:c0de::]/httpboot/foo-os-uki.efi
14 changes: 14 additions & 0 deletions docs/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM squidfunk/mkdocs-material:latest

LABEL project=boot_operator

WORKDIR /docs

COPY docs/requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 8000

# Start development server by default
ENTRYPOINT ["mkdocs"]
CMD ["serve", "--dev-addr=0.0.0.0:8000"]
39 changes: 39 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Boot-Operator Documentation

## Overview

Boot Operator is a Kubernetes-based project designed to automate the deployment of tools required for booting bare metal servers. It integrates web servers and Kubernetes controllers to manage the entire process of provisioning, booting, and configuring the server.

## Problem It Solves

When a bare metal server boots with a network boot method (e.g., PXE or HTTP boot), it typically contacts a DHCP or proxy DHCP server to obtain the necessary information for booting. The DHCP server then provides the IP address of a TFTP server (for PXE) or a web server (for HTTP boot), along with additional boot parameters.

Traditionally, managing these network boot servers requires manual configuration. Boot Operator automates this by incorporating the boot servers into Kubernetes deployments. By leveraging Kubernetes controllers, each machine's boot process is handled declaratively, making it simpler to manage and scale.

## Key Components

Boot Operator includes the following key components:

- **IPXE Boot Server**
- Handles `/ipxe` requests
- Responds with an iPXE script, which the bare metal server uses to download the necessary OS components
- This endpoint is typically called directly by the server during boot and is commonly used in PXE boot scenarios

- **HTTP Boot Server**
- Handles `/httpboot` requests
- Returns a JSON response containing the location of the UKI (Unified Kernel Image) that the server should download
- The DHCP server extension typically handles the response and sends the UKI image location to the server
- Common in modern cloud-native bare metal setups, especially for containers and minimal OS images

- **Image Proxy Server**
- Handles `/image` requests
- Extracts layers from public OCI (Open Container Initiative) images, with current support for GHCR (GitHub Container Registry) only
- Downloads specific layers based on the requested URI and image specifications
- Example:
- `wget http://SERVER_ADDRESS:30007/image?imageName=ghcr.io/ironcore-dev/os-images/gardenlinux&version=1443.10&layerName=application/vnd.ironcore.image.squashfs.v1alpha1.squashfs`

- **Ignition Server**
- Handles `/ignition` requests
- Responds with Ignition configuration content tailored to the client machine, identified by its UUID in the request URL.

These servers leverage Kubernetes controllers and API objects to manage the boot process and serve requests from bare metal machines. The architecture and specifics of the controllers and API objects are described in the architecture section of the documentation.
Loading
Loading