Skip to content

Commit

Permalink
Initial implementation and integration of the OS upgrade script (#16)
Browse files Browse the repository at this point in the history
* Add OS data to release manifest

* Add relevant roles for secret creation

* Add initial logic around OS upgrade script secret creation

* Remove leftover debug code
  • Loading branch information
ipetrov117 committed Jul 23, 2024
1 parent 66923db commit 003e6b2
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 0 deletions.
9 changes: 9 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ rules:
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
- get
- list
- apiGroups:
- ""
resources:
Expand Down
26 changes: 26 additions & 0 deletions internal/controller/reconcile_os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package controller

import (
"context"
"fmt"

"github.com/suse-edge/upgrade-controller/internal/upgrade"
"github.com/suse-edge/upgrade-controller/pkg/release"
ctrl "sigs.k8s.io/controller-runtime"
)

//lint:ignore U1000 - Temporary ignore "unused" linter error. Will be removed when function is ready to be used.
func (r *UpgradePlanReconciler) reconcileOS(ctx context.Context, releaseOS *release.OperatingSystem) (ctrl.Result, error) {
secret, err := upgrade.OSUpgradeSecret(releaseOS)
if err != nil {
return ctrl.Result{}, fmt.Errorf("generating OS upgrade secret: %w", err)
}

if err = r.Create(ctx, secret); err != nil {
return ctrl.Result{}, fmt.Errorf("creating OS upgrade secret: %w", err)
}

// TODO: OS upgrade logic

return ctrl.Result{Requeue: true}, nil
}
1 change: 1 addition & 0 deletions internal/controller/upgradeplan_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type UpgradePlanReconciler struct {
// +kubebuilder:rbac:groups=lifecycle.suse.com,resources=upgradeplans/finalizers,verbs=update
// +kubebuilder:rbac:groups=upgrade.cattle.io,resources=plans,verbs=create;list;get;watch
// +kubebuilder:rbac:groups="",resources=nodes,verbs=watch;list
// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;delete;create
// +kubebuilder:rbac:groups=core,resources=events,verbs=create;patch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
Expand Down
59 changes: 59 additions & 0 deletions internal/upgrade/os.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package upgrade

import (
"bytes"
_ "embed"
"fmt"
"text/template"

"github.com/suse-edge/upgrade-controller/pkg/release"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

//go:embed templates/os-upgrade.sh.tpl
var osUpgradeScript string

func OSUpgradeSecret(releaseOS *release.OperatingSystem) (*corev1.Secret, error) {
const (
scriptName = "os-upgrade.sh"
secretName = "os-upgrade-secret"
)

tmpl, err := template.New(scriptName).Parse(osUpgradeScript)
if err != nil {
return nil, fmt.Errorf("parsing contents: %w", err)
}

values := struct {
CPEScheme string
RepoGPGKey string
ZypperID string
Version string
SupportedArchs []string
}{
CPEScheme: releaseOS.CPEScheme,
RepoGPGKey: releaseOS.RepoGPGPath,
ZypperID: releaseOS.ZypperID,
Version: releaseOS.Version,
SupportedArchs: releaseOS.SupportedArchs,
}

var buff bytes.Buffer
if err = tmpl.Execute(&buff, values); err != nil {
return nil, fmt.Errorf("applying template: %w", err)
}

secret := &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: secretName,
Namespace: upgradeNamespace,
},
Type: corev1.SecretTypeOpaque,
StringData: map[string]string{
scriptName: buff.String(),
},
}

return secret, nil
}
64 changes: 64 additions & 0 deletions internal/upgrade/templates/os-upgrade.sh.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/sh

# Common Platform Enumeration (CPE) comming from the release manifest
RELEASE_CPE={{.CPEScheme}}
# Common Platform Enumeration (CPE) that the system is currently running with
CURRENT_CPE=`cat /etc/os-release | grep -w CPE_NAME | cut -d "=" -f 2 | tr -d '"'`

# Determine whether architecture is supported
SYSTEM_ARCH=`arch`
IFS=' ' read -r -a SUPPORTED_ARCH_ARRAY <<< $(echo "{{.SupportedArchs}}" | tr -d '[]')

found=false
for arch in "${SUPPORTED_ARCH_ARRAY[@]}"; do
if [ "${SYSTEM_ARCH}" == ${arch} ]; then
found=true
break
fi
done

if [ ${found} == false ]; then
echo "Operating system is running an unsupported architecture. System arch: ${SYSTEM_ARCH}. Supported archs: ${SUPPORTED_ARCH_ARRAY[*]}"
exit 1
fi

# Determine whether this is a package update or a migration
if [ "${RELEASE_CPE}" == "${CURRENT_CPE}" ]; then
# Package update if both CPEs are the same
EXEC_START_PRE=""
EXEC_START="/usr/sbin/transactional-update cleanup up"
SERVICE_NAME="os-pkg-update.service"
else
# Migration if the CPEs are different
EXEC_START_PRE="/usr/sbin/transactional-update run rpm --import {{.RepoGPGKey}}"
EXEC_START="/usr/sbin/transactional-update --continue run zypper migration --non-interactive --product {{.ZypperID}}/{{.Version}}/${SYSTEM_ARCH} --root /"
SERVICE_NAME="os-migration.service"
fi

UPDATE_SERVICE_PATH=/etc/systemd/system/${SERVICE_NAME}

echo "Creating ${SERVICE_NAME}..."
cat <<EOF > ${UPDATE_SERVICE_PATH}
[Unit]
Description=SUSE Edge Upgrade Service
ConditionACPower=true
Wants=network.target
After=network.target
[Service]
Type=oneshot
ExecStartPre=${EXEC_START_PRE}
ExecStart=${EXEC_START}
ExecStartPost=-/bin/bash -c '[ -f /run/reboot-needed ] && shutdown -r +1'
IOSchedulingClass=best-effort
IOSchedulingPriority=7
EOF

echo "Starting ${SERVICE_NAME}..."
systemctl start ${SERVICE_NAME} &
tail --pid $! -f cat /var/log/transactional-update.log

echo "Cleaning up..."
# Remove service after it has finished its work
rm ${UPDATE_SERVICE_PATH}
systemctl daemon-reload
8 changes: 8 additions & 0 deletions manifests/release-3.0.1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ components:
version: v1.28.9+k3s1
rke2:
version: v1.28.9+rke2r1
operatingSystem:
version: 6.0
zypperID: SL-Micro
cpeScheme: cpe:/o:suse:sl-micro:6.0
repoGPGPath: /usr/lib/rpm/gnupg/keys/gpg-pubkey-09d9ea69-645b99ce.asc
supportedArchs:
- x86_64
# - aarch64 TODO: add when we start supporting it
9 changes: 9 additions & 0 deletions pkg/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,14 @@ type Release struct {
Version string `yaml:"version"`
} `yaml:"rke2"`
} `yaml:"kubernetes"`
OperatingSystem OperatingSystem `yaml:"operatingSystem"`
} `yaml:"components"`
}

type OperatingSystem struct {
Version string `yaml:"version"`
ZypperID string `yaml:"zypperID"`
CPEScheme string `yaml:"cpeScheme"`
RepoGPGPath string `yaml:"repoGPGPath"`
SupportedArchs []string `yaml:"supportedArchs"`
}

0 comments on commit 003e6b2

Please sign in to comment.