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

Adding use-installer-flag to host agent #502

Merged
merged 3 commits into from
Apr 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions agent/help_flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var _ = Describe("Help flag for host agent", func() {
"--metricsbindaddress string",
"--namespace string",
"--skip-installation",
"--use-installer-controller",
"--version",
"-v, --v",
"--feature-gates mapStringBool",
Expand Down
58 changes: 57 additions & 1 deletion agent/host_agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,9 @@ var _ = Describe("Agent", func() {

BeforeEach(func() {
ns = builder.Namespace("testns").Build()
Expect(k8sClient.Create(context.TODO(), ns)).NotTo(HaveOccurred(), "failed to create test namespace")
ctx = context.TODO()
Expect(k8sClient.Create(ctx, ns)).NotTo(HaveOccurred(), "failed to create test namespace")

var err error
hostName, err = os.Hostname()
Expect(err).NotTo(HaveOccurred())
Expand Down Expand Up @@ -561,4 +562,59 @@ var _ = Describe("Agent", func() {
})

})

Context("When the host agent is executed with --use-installer-controller flag", func() {
var (
ns *corev1.Namespace
ctx context.Context
err error
hostName string
runner *e2e.ByoHostRunner
byoHostContainer *container.ContainerCreateCreatedBody
output dockertypes.HijackedResponse
)

BeforeEach(func() {
ns = builder.Namespace("testns").Build()
ctx = context.TODO()
Expect(k8sClient.Create(ctx, ns)).NotTo(HaveOccurred(), "failed to create test namespace")

hostName, err = os.Hostname()
Expect(err).NotTo(HaveOccurred())

runner = setupTestInfra(ctx, hostName, getKubeConfig().Name(), ns)
runner.CommandArgs["--use-installer-controller"] = ""

byoHostContainer, err = runner.SetupByoDockerHost()
Expect(err).NotTo(HaveOccurred())

})

AfterEach(func() {
cleanup(runner.Context, byoHostContainer, ns, agentLogFile)
})

It("should not call the intree installer", func() {
output, _, err = runner.ExecByoDockerHost(byoHostContainer)
Expect(err).NotTo(HaveOccurred())
defer output.Close()
f := e2e.WriteDockerLog(output, agentLogFile)
defer func() {
deferredErr := f.Close()
if deferredErr != nil {
e2e.Showf("error closing file %s: %v", agentLogFile, deferredErr)
}
}()
Eventually(func() (done bool) {
_, err := os.Stat(agentLogFile)
if err == nil {
data, err := os.ReadFile(agentLogFile)
if err == nil && strings.Contains(string(data), "\"msg\"=\"use-installer-controller flag set, skipping intree installer\"") {
return true
}
}
return false
}, 30).Should(BeTrue())
})
})
})
35 changes: 20 additions & 15 deletions agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func setupflags() {
flag.StringVar(&metricsbindaddress, "metricsbindaddress", ":8080", "metricsbindaddress is the TCP address that the controller should bind to for serving prometheus metrics.It can be set to \"0\" to disable the metrics serving")
flag.StringVar(&downloadpath, "downloadpath", "/var/lib/byoh/bundles", "File System path to keep the downloads")
flag.BoolVar(&skipInstallation, "skip-installation", false, "If you want to skip installation of the kubernetes component binaries")
flag.BoolVar(&useInstallerController, "use-installer-controller", false, "If you want to skip the intree installer and use the default or your own installer controller")
flag.BoolVar(&printVersion, "version", false, "Print the version of the agent")

pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
Expand Down Expand Up @@ -124,14 +125,15 @@ func setupTemplateParser() *cloudinit.TemplateParser {
}

var (
namespace string
scheme *runtime.Scheme
labels = make(labelFlags)
metricsbindaddress string
downloadpath string
skipInstallation bool
printVersion bool
k8sInstaller reconciler.IK8sInstaller
namespace string
scheme *runtime.Scheme
labels = make(labelFlags)
metricsbindaddress string
downloadpath string
skipInstallation bool
useInstallerController bool
printVersion bool
k8sInstaller reconciler.IK8sInstaller
)

// TODO - fix logging
Expand Down Expand Up @@ -197,8 +199,9 @@ func main() {
}

if skipInstallation {
k8sInstaller = nil
logger.Info("skip-installation flag set, skipping installer initialisation")
} else if useInstallerController {
logger.Info("use-installer-controller flag set, skipping intree installer")
} else {
// increasing installer log level to 1, so that it wont be logged by default
k8sInstaller, err = installer.New(downloadpath, installer.BundleTypeK8s, logger.V(1))
Expand All @@ -208,12 +211,14 @@ func main() {
}

hostReconciler := &reconciler.HostReconciler{
Client: k8sClient,
CmdRunner: cloudinit.CmdRunner{},
FileWriter: cloudinit.FileWriter{},
TemplateParser: setupTemplateParser(),
Recorder: mgr.GetEventRecorderFor("hostagent-controller"),
K8sInstaller: k8sInstaller,
Client: k8sClient,
CmdRunner: cloudinit.CmdRunner{},
FileWriter: cloudinit.FileWriter{},
TemplateParser: setupTemplateParser(),
Recorder: mgr.GetEventRecorderFor("hostagent-controller"),
K8sInstaller: k8sInstaller,
SkipK8sInstallation: skipInstallation,
UseInstallerController: useInstallerController,
}

if err = hostReconciler.SetupWithManager(context.TODO(), mgr); err != nil {
Expand Down
25 changes: 17 additions & 8 deletions agent/reconciler/host_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ type IK8sInstaller interface {

// HostReconciler encapsulates the data/logic needed to reconcile a ByoHost
type HostReconciler struct {
Client client.Client
CmdRunner cloudinit.ICmdRunner
FileWriter cloudinit.IFileWriter
TemplateParser cloudinit.ITemplateParser
Recorder record.EventRecorder
K8sInstaller IK8sInstaller
Client client.Client
CmdRunner cloudinit.ICmdRunner
FileWriter cloudinit.IFileWriter
TemplateParser cloudinit.ITemplateParser
Recorder record.EventRecorder
K8sInstaller IK8sInstaller
SkipK8sInstallation bool
UseInstallerController bool
}

const (
Expand Down Expand Up @@ -112,8 +114,14 @@ func (r *HostReconciler) reconcileNormal(ctx context.Context, byoHost *infrastru
return ctrl.Result{}, err
}

if r.K8sInstaller == nil {
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 {
err = r.installK8sComponents(ctx, byoHost)
if err != nil {
Expand Down Expand Up @@ -205,7 +213,7 @@ func (r *HostReconciler) hostCleanUp(ctx context.Context, byoHost *infrastructur
if err != nil {
return err
}
if r.K8sInstaller == nil {
if r.SkipK8sInstallation {
logger.Info("Skipping uninstallation of k8s components")
} else {
err = r.uninstallk8sComponents(ctx, byoHost)
Expand Down Expand Up @@ -263,6 +271,7 @@ func (r *HostReconciler) installK8sComponents(ctx context.Context, byoHost *infr
bundleRegistry := byoHost.GetAnnotations()[infrastructurev1beta1.BundleLookupBaseRegistryAnnotation]
k8sVersion := byoHost.GetAnnotations()[infrastructurev1beta1.K8sVersionAnnotation]
byohBundleTag := byoHost.GetAnnotations()[infrastructurev1beta1.BundleLookupTagAnnotation]

err := r.K8sInstaller.Install(bundleRegistry, k8sVersion, byohBundleTag)
if err != nil {
return err
Expand Down
54 changes: 48 additions & 6 deletions agent/reconciler/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ var _ = Describe("Byohost Agent Tests", func() {
fakeInstaller = &reconcilerfakes.FakeIK8sInstaller{}
recorder = record.NewFakeRecorder(32)
hostReconciler = &reconciler.HostReconciler{
Client: k8sClient,
CmdRunner: fakeCommandRunner,
FileWriter: fakeFileWriter,
TemplateParser: fakeTemplateParser,
Recorder: recorder,
K8sInstaller: nil,
Client: k8sClient,
CmdRunner: fakeCommandRunner,
FileWriter: fakeFileWriter,
TemplateParser: fakeTemplateParser,
Recorder: recorder,
K8sInstaller: nil,
SkipK8sInstallation: false,
UseInstallerController: false,
}
})

Expand Down Expand Up @@ -177,6 +179,36 @@ runCmd:
Expect(patchHelper.Patch(ctx, byoHost, patch.WithStatusObservedGeneration{})).NotTo(HaveOccurred())
})

Context("When use-installer-controller is set", func() {
BeforeEach(func() {
hostReconciler.UseInstallerController = true
})

It("should set the Reason to InstallationSecretUnavailableReason", func() {
result, reconcilerErr := hostReconciler.Reconcile(ctx, controllerruntime.Request{
NamespacedName: byoHostLookupKey,
})
Expect(result).To(Equal(controllerruntime.Result{}))
Expect(reconcilerErr).ToNot(HaveOccurred())

updatedByoHost := &infrastructurev1beta1.ByoHost{}
err := k8sClient.Get(ctx, byoHostLookupKey, updatedByoHost)
Expect(err).ToNot(HaveOccurred())

byoHostRegistrationSucceeded := conditions.Get(updatedByoHost, infrastructurev1beta1.K8sNodeBootstrapSucceeded)
Expect(*byoHostRegistrationSucceeded).To(conditions.MatchCondition(clusterv1.Condition{
Type: infrastructurev1beta1.K8sNodeBootstrapSucceeded,
Status: corev1.ConditionFalse,
Reason: infrastructurev1beta1.K8sInstallationSecretUnavailableReason,
Severity: clusterv1.ConditionSeverityInfo,
}))
})

AfterEach(func() {
hostReconciler.UseInstallerController = false
})
})

It("should set K8sComponentsInstallationSucceeded to false with Reason K8sComponentsInstallationFailedReason if Install fails", func() {
hostReconciler.K8sInstaller = fakeInstaller
fakeInstaller.InstallReturns(errors.New("k8s components install failed"))
Expand All @@ -201,6 +233,7 @@ runCmd:
})

It("should set K8sNodeBootstrapSucceeded to false with Reason CloudInitExecutionFailedReason if the bootstrap execution fails", func() {
hostReconciler.K8sInstaller = fakeInstaller
fakeCommandRunner.RunCmdReturns(errors.New("I failed"))

result, reconcilerErr := hostReconciler.Reconcile(ctx, controllerruntime.Request{
Expand All @@ -225,13 +258,15 @@ runCmd:
// assert events
events := eventutils.CollectEvents(recorder.Events)
Expect(events).Should(ConsistOf([]string{
"Normal k8sComponentInstalled Successfully Installed K8s components",
"Warning BootstrapK8sNodeFailed k8s Node Bootstrap failed",
// TODO: improve test to remove this event
"Warning ResetK8sNodeFailed k8s Node Reset failed",
}))
})

It("should set K8sNodeBootstrapSucceeded to True if the boostrap execution succeeds", func() {
hostReconciler.K8sInstaller = fakeInstaller
result, reconcilerErr := hostReconciler.Reconcile(ctx, controllerruntime.Request{
NamespacedName: byoHostLookupKey,
})
Expand All @@ -254,11 +289,13 @@ runCmd:
// assert events
events := eventutils.CollectEvents(recorder.Events)
Expect(events).Should(ConsistOf([]string{
"Normal k8sComponentInstalled Successfully Installed K8s components",
"Normal BootstrapK8sNodeSucceeded k8s Node Bootstraped",
}))
})

It("should skip k8s installation if skip-installation is set", func() {
hostReconciler.SkipK8sInstallation = true
result, reconcilerErr := hostReconciler.Reconcile(ctx, controllerruntime.Request{
NamespacedName: byoHostLookupKey,
})
Expand All @@ -283,6 +320,7 @@ runCmd:
})

It("should execute bootstrap secret only once ", func() {
hostReconciler.K8sInstaller = fakeInstaller
_, reconcilerErr := hostReconciler.Reconcile(ctx, controllerruntime.Request{
NamespacedName: byoHostLookupKey,
})
Expand All @@ -299,6 +337,7 @@ runCmd:

AfterEach(func() {
Expect(k8sClient.Delete(ctx, bootstrapSecret)).NotTo(HaveOccurred())
hostReconciler.SkipK8sInstallation = false
})
})

Expand Down Expand Up @@ -349,6 +388,7 @@ runCmd:
})

It("should reset the node and set the Reason to K8sNodeAbsentReason", func() {
hostReconciler.K8sInstaller = fakeInstaller
result, reconcilerErr := hostReconciler.Reconcile(ctx, controllerruntime.Request{
NamespacedName: byoHostLookupKey,
})
Expand Down Expand Up @@ -386,6 +426,7 @@ runCmd:
})

It("should skip uninstallation if skip-installation flag is set", func() {
hostReconciler.SkipK8sInstallation = true
result, reconcilerErr := hostReconciler.Reconcile(ctx, controllerruntime.Request{
NamespacedName: byoHostLookupKey,
})
Expand Down Expand Up @@ -455,6 +496,7 @@ runCmd:

AfterEach(func() {
Expect(k8sClient.Delete(ctx, byoHost)).NotTo(HaveOccurred())
hostReconciler.SkipK8sInstallation = false
})
})
})
5 changes: 5 additions & 0 deletions apis/infrastructure/v1beta1/condition_consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ const (
// This secret is available on byohost.Spec.BootstrapSecret field
BootstrapDataSecretUnavailableReason = "BootstrapDataSecretUnavailable"

// K8sInstallationSecretUnavailableReason indicates that the installer controller is yet to provide the
// secret that contains installation and uninstallation scripts
// This secret is available on byohost.Spec.K8sInstallationSecret field
K8sInstallationSecretUnavailableReason = "K8sInstallationSecretUnavailable"

// CleanK8sDirectoriesFailedReason indicates that clean k8s directories failed for some reason, please
// delete it manually for reconcile to proceed.
// The cleaned directories are /run/kubeadm and /etc/cni/net.d
Expand Down