Skip to content

Commit

Permalink
feat: ship Environment "default"
Browse files Browse the repository at this point in the history
Closes #311.

Signed-off-by: Alexey Palazhchenko <alexey.palazhchenko@gmail.com>
  • Loading branch information
AlekSi authored and talos-bot committed May 18, 2021
1 parent 2e8c1ed commit 4a1183b
Show file tree
Hide file tree
Showing 18 changed files with 250 additions and 145 deletions.
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ LABEL org.opencontainers.image.source https://github.com/talos-systems/sidero
ENTRYPOINT [ "/manager" ]

FROM base AS build-metal-controller-manager
ARG TALOS_RELEASE
ARG TARGETARCH
ARG GO_BUILDFLAGS
RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=${TARGETARCH} go build ${GO_BUILDFLAGS} -ldflags "-s -w" -o /manager ./app/metal-controller-manager
RUN --mount=type=cache,target=/.cache GOOS=linux GOARCH=${TARGETARCH} go build ${GO_BUILDFLAGS} -ldflags "-s -w -X main.TalosRelease=${TALOS_RELEASE}" -o /manager ./app/metal-controller-manager
RUN chmod +x /manager

FROM base AS agent-build-amd64
Expand Down
31 changes: 31 additions & 0 deletions app/metal-controller-manager/api/v1alpha1/environment_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@
package v1alpha1

import (
"fmt"
"sort"

"github.com/talos-systems/talos/pkg/machinery/kernel"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EnvironmentDefault is an automatically created Environment.
const EnvironmentDefault = "default"

type Asset struct {
URL string `json:"url,omitempty"`
SHA512 string `json:"sha512,omitempty"`
Expand Down Expand Up @@ -65,6 +72,30 @@ type EnvironmentList struct {
Items []Environment `json:"items"`
}

// EnvironmentDefaultSpec returns EnvironmentDefault's spec.
func EnvironmentDefaultSpec(talosRelease, apiEndpoint string, apiPort uint16) *EnvironmentSpec {
args := make([]string, 0, len(kernel.DefaultArgs)+6)
args = append(args, kernel.DefaultArgs...)
args = append(args, "console=tty0", "console=ttyS1,115200n8", "earlyprintk=ttyS1,115200n8")
args = append(args, "initrd=initramfs.xz", "talos.platform=metal")
args = append(args, fmt.Sprintf("talos.config=http://%s:%d/configdata?uuid=", apiEndpoint, apiPort))
sort.Strings(args)

return &EnvironmentSpec{
Kernel: Kernel{
Asset: Asset{
URL: fmt.Sprintf("https://github.com/talos-systems/talos/releases/download/%s/vmlinuz-amd64", talosRelease),
},
Args: args,
},
Initrd: Initrd{
Asset: Asset{
URL: fmt.Sprintf("https://github.com/talos-systems/talos/releases/download/%s/initramfs-amd64.xz", talosRelease),
},
},
}
}

func init() {
SchemeBuilder.Register(&Environment{}, &EnvironmentList{})
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ metadata:
name: default
spec:
kernel:
url: 'https://github.com/talos-systems/talos/releases/download/v0.4.0-alpha.5/vmlinuz'
sha512: ''
url: "https://github.com/talos-systems/talos/releases/download/v0.10.2/vmlinuz-amd64"
sha512: ""
args:
- initrd=initramfs.xz
- page_poison=1
- slab_nomerge
- slub_debug=P
- pti=on
- random.trust_cpu=on
- ima_template=ima-ng
- console=tty0
- console=ttyS1,115200n8
- consoleblank=0
- earlyprintk=ttyS1,115200n8
- ima_appraise=fix
- ima_hash=sha512
- console=tty0
- console=ttyS0
- ima_template=ima-ng
- init_on_alloc=1
- initrd=initramfs.xz
- nvme_core.io_timeout=4294967295
- printk.devkmsg=on
- pti=on
- random.trust_cpu=on
- slab_nomerge=
- talos.config=http://192.168.1.10:8081/configdata?uuid=
- talos.platform=metal
- talos.config=http://192.168.1.10:8080/assets/controlplane.yaml
initrd:
url: 'https://github.com/talos-systems/talos/releases/download/v0.4.0-alpha.5/initramfs.xz'
sha512: ''
url: "https://github.com/talos-systems/talos/releases/download/v0.10.2/initramfs-amd64.xz"
sha512: ""
68 changes: 50 additions & 18 deletions app/metal-controller-manager/controllers/environment_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
multierror "github.com/hashicorp/go-multierror"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
Expand All @@ -30,37 +31,38 @@ import (
// EnvironmentReconciler reconciles a Environment object.
type EnvironmentReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
Log logr.Logger
Scheme *runtime.Scheme
TalosRelease string
APIEndpoint string
APIPort uint16
}

// +kubebuilder:rbac:groups=metal.sidero.dev,resources=environments,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=metal.sidero.dev,resources=environments/status,verbs=get;update;patch

func (r *EnvironmentReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
return r.reconcile(req)
}

func (r *EnvironmentReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
return ctrl.NewControllerManagedBy(mgr).
WithOptions(options).
For(&metalv1alpha1.Environment{}).
Complete(r)
}

func (r *EnvironmentReconciler) reconcile(req ctrl.Request) (ctrl.Result, error) {
ctx := context.Background()

l := r.Log.WithValues("environment", req.Name)
l.Info("reconciling")

//nolint:godox
// TODO: We probably should use admission webhooks instead (or in additional) to prevent
// unwanted edits instead of "fixing" the resource after the fact.
if req.Name == metalv1alpha1.EnvironmentDefault {
if err := ReconcileEnvironmentDefault(ctx, r.Client, r.TalosRelease, r.APIEndpoint, r.APIPort); err != nil {
return ctrl.Result{}, err
}

// do not return; re-reconcile it to update status
} //nolint:wsl

var env metalv1alpha1.Environment

if err := r.Get(ctx, req.NamespacedName, &env); err != nil {
if apierrors.IsNotFound(err) {
return ctrl.Result{}, nil
}

return ctrl.Result{}, fmt.Errorf("unable to get environment: %w", err)
l.Error(err, "failed fetching resource")
return ctrl.Result{}, client.IgnoreNotFound(err)
}

envs := filepath.Join("/var/lib/sidero/env", env.GetName())
Expand Down Expand Up @@ -180,6 +182,36 @@ func (r *EnvironmentReconciler) reconcile(req ctrl.Request) (ctrl.Result, error)
return ctrl.Result{}, nil
}

// ReconcileEnvironmentDefault ensures that Environment "default" exist.
func ReconcileEnvironmentDefault(ctx context.Context, c client.Client, talosRelease, apiEndpoint string, apiPort uint16) error {
key := types.NamespacedName{
Name: metalv1alpha1.EnvironmentDefault,
}

env := metalv1alpha1.Environment{}
err := c.Get(ctx, key, &env)

if apierrors.IsNotFound(err) {
env.Name = metalv1alpha1.EnvironmentDefault
env.Spec = *metalv1alpha1.EnvironmentDefaultSpec(talosRelease, apiEndpoint, apiPort)

err = c.Create(ctx, &env)
}

return err
}

func (r *EnvironmentReconciler) SetupWithManager(mgr ctrl.Manager, options controller.Options) error {
if r.TalosRelease == "" {
return errors.New("TalosRelease is not set")
}

return ctrl.NewControllerManagedBy(mgr).
WithOptions(options).
For(&metalv1alpha1.Environment{}).
Complete(r)
}

func save(ctx context.Context, asset metalv1alpha1.Asset, file string) error {
url := asset.URL

Expand Down
22 changes: 11 additions & 11 deletions app/metal-controller-manager/internal/ipxe/ipxe_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,20 +305,20 @@ func newEnvironment(server *metalv1alpha1.Server, serverBinding *infrav1.ServerB

func newAgentEnvironment(arch string) *metalv1alpha1.Environment {
args := []string{
"initrd=initramfs.xz",
"page_poison=1",
"slab_nomerge",
"slub_debug=P",
"pti=on",
"panic=30",
"random.trust_cpu=on",
"ima_template=ima-ng",
"console=tty0",
"console=ttyS0",
"ima_appraise=fix",
"ima_hash=sha512",
"ima_template=ima-ng",
"initrd=initramfs.xz",
"ip=dhcp",
"console=tty0",
"console=ttyS0",
"page_poison=1",
"panic=30",
"printk.devkmsg=on",
"pti=on",
"random.trust_cpu=on",
"slab_nomerge=",
"slub_debug=P",
fmt.Sprintf("%s=%s:%d", constants.AgentEndpointArg, apiEndpoint, apiPort),
}

Expand Down Expand Up @@ -347,7 +347,7 @@ func newAgentEnvironment(arch string) *metalv1alpha1.Environment {
func newDefaultEnvironment() (env *metalv1alpha1.Environment, err error) {
env = &metalv1alpha1.Environment{}

if err := c.Get(context.Background(), types.NamespacedName{Namespace: "", Name: "default"}, env); err != nil {
if err := c.Get(context.Background(), types.NamespacedName{Namespace: "", Name: metalv1alpha1.EnvironmentDefault}, env); err != nil {
return nil, err
}

Expand Down
40 changes: 28 additions & 12 deletions app/metal-controller-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ const (
)

var (
// TalosRelease is set as a build argument.
TalosRelease string

scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)
Expand Down Expand Up @@ -93,6 +96,11 @@ func main() {

flag.Parse()

// we can't continue without it
if TalosRelease == "" {
panic("TalosRelease is not set during the build")
}

// workaround for clusterctl not accepting empty value as default value
if extraAgentKernelArgs == "-" {
extraAgentKernelArgs = ""
Expand All @@ -102,6 +110,15 @@ func main() {
apiEndpoint = ""
}

if apiEndpoint == "" {
if endpoint, ok := os.LookupEnv("API_ENDPOINT"); ok {
apiEndpoint = endpoint
} else {
setupLog.Error(fmt.Errorf("no api endpoint found"), "")
os.Exit(1)
}
}

ctrl.SetLogger(zap.New(func(o *zap.Options) {
o.Development = true
}))
Expand Down Expand Up @@ -148,9 +165,12 @@ func main() {
corev1.EventSource{Component: "sidero-controller-manager"})

if err = (&controllers.EnvironmentReconciler{
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("Environment"),
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
Log: ctrl.Log.WithName("controllers").WithName("Environment"),
Scheme: mgr.GetScheme(),
TalosRelease: TalosRelease,
APIEndpoint: apiEndpoint,
APIPort: uint16(apiPort),
}).SetupWithManager(mgr, controller.Options{MaxConcurrentReconciles: defaultMaxConcurrentReconciles}); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Environment")
os.Exit(1)
Expand Down Expand Up @@ -191,15 +211,6 @@ func main() {

setupLog.Info("starting iPXE server")

if apiEndpoint == "" {
if endpoint, ok := os.LookupEnv("API_ENDPOINT"); ok {
apiEndpoint = endpoint
} else {
setupLog.Error(fmt.Errorf("no api endpoint found"), "unable to start iPXE server", "controller", "Environment")
os.Exit(1)
}
}

if err := ipxe.RegisterIPXE(httpMux, apiEndpoint, apiPort, extraAgentKernelArgs, apiPort, mgr.GetClient()); err != nil {
setupLog.Error(err, "unable to start iPXE server", "controller", "Environment")
os.Exit(1)
Expand Down Expand Up @@ -231,6 +242,11 @@ func main() {
os.Exit(1)
}

if err = controllers.ReconcileEnvironmentDefault(context.TODO(), k8sClient, TalosRelease, apiEndpoint, uint16(apiPort)); err != nil {
setupLog.Error(err, `failed to reconcile Environment "default"`)
os.Exit(1)
}

setupLog.Info("starting manager and HTTP server")

var eg errgroup.Group
Expand Down
24 changes: 12 additions & 12 deletions docs/website/content/docs/v0.3/Configuration/environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The hierarchy from most to least respected is:

- `.spec.environmentRef` provided at `Server` level
- `.spec.environmentRef` provided at `ServerClass` level
- `"default"` `Environment` created by administrator
- `"default"` `Environment` created automatically and modified by an administrator

A sample environment definition looks like this:

Expand All @@ -30,22 +30,22 @@ spec:
url: "https://github.com/talos-systems/talos/releases/download/v0.10.2/vmlinuz-amd64"
sha512: ""
args:
- init_on_alloc=1
- init_on_free=1
- slab_nomerge
- pti=on
- consoleblank=0
- random.trust_cpu=on
- ima_template=ima-ng
- ima_appraise=fix
- ima_hash=sha512
- console=tty0
- console=ttyS1,115200n8
- consoleblank=0
- earlyprintk=ttyS1,115200n8
- panic=0
- ima_appraise=fix
- ima_hash=sha512
- ima_template=ima-ng
- init_on_alloc=1
- initrd=initramfs.xz
- nvme_core.io_timeout=4294967295
- printk.devkmsg=on
- talos.platform=metal
- pti=on
- random.trust_cpu=on
- slab_nomerge=
- talos.config=http://$PUBLIC_IP:8081/configdata?uuid=
- talos.platform=metal
initrd:
url: "https://github.com/talos-systems/talos/releases/download/v0.10.2/initramfs-amd64.xz"
sha512: ""
Expand Down
Loading

0 comments on commit 4a1183b

Please sign in to comment.