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.GetBYOHConfigPath())
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
91 changes: 87 additions & 4 deletions agent/reconciler/host_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"
"os"
"os/exec"

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

const (
Expand Down Expand Up @@ -94,6 +96,8 @@ 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, "")
Expand All @@ -117,10 +121,20 @@ 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
if !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.executeInstallerController(ctx, byoHost)
if err != nil {
return ctrl.Result{}, err
}
r.Recorder.Event(byoHost, corev1.EventTypeNormal, "InstallScriptExecutionSucceeded", "install script executed")
conditions.MarkTrue(byoHost, infrastructurev1beta1.K8sComponentsInstallationSucceeded)
} else {
logger.Info("install script already executed")
}
} else {
err = r.installK8sComponents(ctx, byoHost)
Expand Down Expand Up @@ -156,6 +170,34 @@ func (r *HostReconciler) reconcileNormal(ctx context.Context, byoHost *infrastru
return ctrl.Result{}, nil
}

func (r *HostReconciler) executeInstallerController(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) error {
logger := ctrl.LoggerFrom(ctx)
secret := &corev1.Secret{}
err := r.Client.Get(ctx, types.NamespacedName{Name: byoHost.Spec.InstallationSecret.Name, Namespace: byoHost.Spec.InstallationSecret.Namespace}, secret)
if err != nil {
logger.Error(err, "error getting install and uninstall script")
r.Recorder.Eventf(byoHost, corev1.EventTypeWarning, "ReadInstallationSecretFailed", "install and uninstall script %s not found", byoHost.Spec.InstallationSecret.Name)
return err
}
installScript := string(secret.Data["install"])
uninstallScript := string(secret.Data["uninstall"])

byoHost.Spec.UninstallationScript = &uninstallScript
installScript, err = r.parseScript(ctx, installScript)
if err != nil {
return 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 executing installation script")
r.Recorder.Event(byoHost, corev1.EventTypeWarning, "InstallScriptExecutionFailed", "install script execution failed")
conditions.MarkFalse(byoHost, infrastructurev1beta1.K8sComponentsInstallationSucceeded, infrastructurev1beta1.K8sComponentsInstallationFailedReason, clusterv1.ConditionSeverityInfo, "")
return err
}
return nil
}

func (r *HostReconciler) reconcileDelete(ctx context.Context, byoHost *infrastructurev1beta1.ByoHost) (ctrl.Result, error) {
return ctrl.Result{}, nil
}
Expand All @@ -171,6 +213,28 @@ func (r *HostReconciler) getBootstrapScript(ctx context.Context, dataSecretName,
return bootstrapSecret, 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) {
data, err := cloudinit.TemplateParser{
Template: map[string]string{
"BundleDownloadPath": r.DownloadPath,
},
}.ParseTemplate(script)
if err != nil {
return "", fmt.Errorf("unable to apply install parsed template to the data object")
}
return data, 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 @@ -215,6 +279,23 @@ func (r *HostReconciler) hostCleanUp(ctx context.Context, byoHost *infrastructur
}
if r.SkipK8sInstallation {
logger.Info("Skipping uninstallation of k8s components")
} else 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.parseScript(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 {
err = r.uninstallk8sComponents(ctx, byoHost)
if err != nil {
Expand All @@ -236,6 +317,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