Skip to content

Commit

Permalink
Add initial logic around OS upgrade script secret creation
Browse files Browse the repository at this point in the history
  • Loading branch information
ipetrov117 committed Jul 23, 2024
1 parent 39ad2be commit e997beb
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
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
}
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
}
65 changes: 65 additions & 0 deletions internal/upgrade/templates/os-upgrade.sh.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/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
echo "$arch"
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

0 comments on commit e997beb

Please sign in to comment.