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

Host agent changes #564

Merged
merged 19 commits into from
Jun 7, 2022
4 changes: 2 additions & 2 deletions agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ func main() {
os.Exit(1)
}
}
// Handle kubeconfig flag
// first look in the byoh path for the kubeconfig
// Handle kubeconfig flag first look in the byoh path for the kubeconfig
config, err := registration.LoadRESTClientConfig(registration.ConfigPath)
if err != nil {
logger.Error(err, "client config load failed")
Expand Down Expand Up @@ -231,6 +230,7 @@ func main() {
K8sInstaller: k8sInstaller,
SkipK8sInstallation: skipInstallation,
UseInstallerController: useInstallerController,
DownloadPath: downloadpath,
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
}
if err = hostReconciler.SetupWithManager(context.TODO(), mgr); err != nil {
logger.Error(err, "unable to create controller")
Expand Down
108 changes: 100 additions & 8 deletions agent/reconciler/host_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
package reconciler

import (
"bytes"
"context"
"fmt"
"html/template"
"os"
"os/exec"

"github.com/pkg/errors"
"github.com/vmware-tanzu/cluster-api-provider-bringyourownhost/agent/cloudinit"
Expand Down Expand Up @@ -45,6 +48,7 @@ type HostReconciler struct {
K8sInstaller IK8sInstaller
SkipK8sInstallation bool
UseInstallerController bool
DownloadPath string
}

const (
Expand Down Expand Up @@ -94,12 +98,28 @@ func (r *HostReconciler) Reconcile(ctx context.Context, req ctrl.Request) (_ ctr

func (r *HostReconciler) reconcileNormal(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) (ctrl.Result, error) {
logger := ctrl.LoggerFrom(ctx)
logger = logger.WithValues("ByoHost", byoHost.Name)
logger.Info("reconcile normal")
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
if byoHost.Status.MachineRef == nil {
logger.Info("Machine ref not yet set")
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sNodeBootstrapSucceeded, infrastructurev1beta1.WaitingForMachineRefReason, clusterv1.ConditionSeverityInfo, "")
return ctrl.Result{}, nil
}

if r.UseInstallerController && !conditions.IsTrue(byoHost, infrastructurev1beta1.K8sComponentsInstallationSucceeded) {
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
if byoHost.Spec.InstallationSecret == nil {
logger.Info("InstallationSecret not ready")
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sComponentsInstallationSucceeded, infrastructurev1beta1.K8sInstallationSecretUnavailableReason, clusterv1.ConditionSeverityInfo, "")
return ctrl.Result{}, nil
}
_, err := r.installerController(ctx, byoHost)
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return ctrl.Result{}, err
}
r.Recorder.Event(byoHost, corev1.EventTypeNormal, "InstallScriptExecutionSucceeded", "install script executed")
conditions.MarkTrue(byoHost, infrastructurev1beta1.K8sComponentsInstallationSucceeded)
}

if byoHost.Spec.BootstrapSecret == nil {
logger.Info("BootstrapDataSecret not ready")
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sNodeBootstrapSucceeded, infrastructurev1beta1.BootstrapDataSecretUnavailableReason, clusterv1.ConditionSeverityInfo, "")
Expand All @@ -116,13 +136,7 @@ func (r *HostReconciler) reconcileNormal(ctx context.Context, byoHost *infrastru

if r.SkipK8sInstallation {
logger.Info("Skipping installation of k8s components")
} else if r.UseInstallerController {
if byoHost.Spec.InstallationSecret == nil {
logger.Info("K8sInstallationSecret not ready")
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sNodeBootstrapSucceeded, infrastructurev1beta1.K8sInstallationSecretUnavailableReason, clusterv1.ConditionSeverityInfo, "")
return ctrl.Result{}, nil
}
} else {
} else if !r.UseInstallerController {
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
err = r.installK8sComponents(ctx, byoHost)
if err != nil {
logger.Error(err, "error in installing k8s components")
Expand Down Expand Up @@ -156,6 +170,29 @@ func (r *HostReconciler) reconcileNormal(ctx context.Context, byoHost *infrastru
return ctrl.Result{}, nil
}

func (r *HostReconciler) installerController(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) (ctrl.Result, error) {
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
logger := ctrl.LoggerFrom(ctx)
installScript, uninstallScript, err := r.getInstallationScript(ctx, byoHost.Spec.InstallationSecret.Name, byoHost.Spec.InstallationSecret.Namespace)
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
logger.Error(err, "error getting installation script")
r.Recorder.Eventf(byoHost, corev1.EventTypeWarning, "ReadInstallationSecretFailed", "installation secret %s not found", byoHost.Spec.InstallationSecret.Name)
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
return ctrl.Result{}, err
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
}
byoHost.Spec.UninstallationScript = &uninstallScript
installScript, err = r.parseInstallationScript(ctx, installScript)
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return ctrl.Result{}, err
}
logger.Info("executing install script")
err = r.executeScript(ctx, installScript)
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
logger.Error(err, "error execting installation script")
r.Recorder.Event(byoHost, corev1.EventTypeWarning, "InstallScriptExecutionFailed", "install script execution failed")
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
}

func (r *HostReconciler) reconcileDelete(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) (ctrl.Result, error) {
return ctrl.Result{}, nil
}
Expand All @@ -171,6 +208,42 @@ func (r *HostReconciler) getBootstrapScript(ctx context.Context, dataSecretName,
return bootstrapSecret, nil
}

func (r *HostReconciler) getInstallationScript(ctx context.Context, dataSecretName, namespace string) (install, uninstall string, err error) {
secret := &corev1.Secret{}
err = r.Client.Get(ctx, types.NamespacedName{Name: dataSecretName, Namespace: namespace}, secret)
if err != nil {
return "", "", err
}

installScript := string(secret.Data["install"])
uninstallScript := string(secret.Data["uninstall"])
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
return installScript, uninstallScript, nil
}

func (r *HostReconciler) executeScript(ctx context.Context, script string) error {
cmd := exec.CommandContext(ctx, "/bin/bash", "-c", script)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
return err
}
return nil
}

func (r *HostReconciler) parseScript(ctx context.Context, script string) (string, error) {
parser, err := template.New("parser").Parse(script)
anusha94 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return "", fmt.Errorf("unable to parse install script")
}
var tpl bytes.Buffer
if err = parser.Execute(&tpl, map[string]string{
"BundleDownloadPath": r.DownloadPath,
}); err != nil {
return "", fmt.Errorf("unable to apply install parsed template to the data object")
}
return tpl.String(), nil
}

// SetupWithManager sets up the controller with the manager
func (r *HostReconciler) SetupWithManager(ctx context.Context, mgr manager.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Expand Down Expand Up @@ -213,7 +286,24 @@ func (r *HostReconciler) hostCleanUp(ctx context.Context, byoHost *infrastructur
if err != nil {
return err
}
if r.SkipK8sInstallation {
if r.UseInstallerController {
if byoHost.Spec.UninstallationScript == nil {
return fmt.Errorf("UninstallationScript not found in Byohost %s", byoHost.Name)
}
logger.Info("Executing Uninstall script")
uninstallScript := *byoHost.Spec.UninstallationScript
uninstallScript, err = r.parseInstallationScript(ctx, uninstallScript)
if err != nil {
logger.Error(err, "error parsing Uninstallation script")
return err
}
err = r.executeScript(ctx, uninstallScript)
if err != nil {
logger.Error(err, "error execting Uninstallation script")
r.Recorder.Event(byoHost, corev1.EventTypeWarning, "UninstallScriptExecutionFailed", "uninstall script execution failed")
return err
}
} else if r.SkipK8sInstallation {
khannakshat7 marked this conversation as resolved.
Show resolved Hide resolved
logger.Info("Skipping uninstallation of k8s components")
} else {
err = r.uninstallk8sComponents(ctx, byoHost)
Expand All @@ -236,6 +326,8 @@ func (r *HostReconciler) hostCleanUp(ctx context.Context, byoHost *infrastructur
return err
}

byoHost.Spec.InstallationSecret = nil
byoHost.Spec.UninstallationScript = nil
r.removeAnnotations(ctx, byoHost)
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sNodeBootstrapSucceeded, infrastructurev1beta1.K8sNodeAbsentReason, clusterv1.ConditionSeverityInfo, "")
return nil
Expand Down
Loading