From 2807ad00ffb72fa3f88cb4bc5406262d6a40bece Mon Sep 17 00:00:00 2001 From: Dasha Komsa Date: Fri, 16 Feb 2024 19:23:46 +0000 Subject: [PATCH] limit the number of artifacts directories retained on disk Signed-off-by: Dasha Komsa --- cmd/provider/main.go | 3 ++- internal/ansible/ansible.go | 26 +++++++++++++++----- internal/controller/ansible.go | 6 ++--- internal/controller/ansibleRun/ansibleRun.go | 13 +++++----- internal/controller/config/config.go | 2 +- 5 files changed, 33 insertions(+), 17 deletions(-) diff --git a/cmd/provider/main.go b/cmd/provider/main.go index 2e86fe4..1d55634 100644 --- a/cmd/provider/main.go +++ b/cmd/provider/main.go @@ -42,6 +42,7 @@ func main() { timeout = app.Flag("timeout", "Controls how long Ansible processes may run before they are killed.").Default("20m").Duration() leaderElection = app.Flag("leader-election", "Use leader election for the controller manager.").Short('l').Default("false").OverrideDefaultFromEnvar("LEADER_ELECTION").Bool() maxReconcileRate = app.Flag("max-reconcile-rate", "The maximum number of concurrent reconciliation operations.").Default("1").Int() + artifactsHistoryLimit = app.Flag("artifacts-history-limit", "Each attempt to run the playbook/role generates a set of artifacts on disk. This settings limits how many of these to keep.").Default("50").Int() ) kingpin.MustParse(app.Parse(os.Args[1:])) @@ -76,6 +77,6 @@ func main() { Features: &feature.Flags{}, } - kingpin.FatalIfError(ansible.Setup(mgr, o, *ansibleCollectionsPath, *ansibleRolesPath, *timeout), "Cannot setup Ansible controllers") + kingpin.FatalIfError(ansible.Setup(mgr, o, *ansibleCollectionsPath, *ansibleRolesPath, *timeout, *artifactsHistoryLimit), "Cannot setup Ansible controllers") kingpin.FatalIfError(mgr.Start(ctrl.SetupSignalHandler()), "Cannot start controller manager") } diff --git a/internal/ansible/ansible.go b/internal/ansible/ansible.go index cb9fbc3..c9b7c49 100644 --- a/internal/ansible/ansible.go +++ b/internal/ansible/ansible.go @@ -27,6 +27,7 @@ import ( "os/exec" "os/user" "path/filepath" + "strconv" "time" "github.com/apenella/go-ansible/pkg/stdoutcallback/results" @@ -69,6 +70,8 @@ type Parameters struct { CollectionsPath string // The source of this filed is either controller flag `--ansible-roles-path` or the env vars : `ANSIBLE_ROLES_PATH` , DEFAULT_ROLES_PATH` RolesPath string + // the limit on the number of artifact directories to keep for each run + ArtifactsHistoryLimit int } // RunPolicy represents the run policies of Ansible. @@ -144,6 +147,14 @@ func withAnsibleRunPolicy(p *RunPolicy) runnerOption { } } +// withArtifactsHistoryLimit sets the limit on the number of artifacts +// directories to keep; each invocation of ansible-runner produces an artifacts directory. +func withArtifactsHistoryLimit(limit int) runnerOption { + return func(r *Runner) { + r.artifactsHistoryLimit = limit + } +} + type cmdFuncType func(behaviorVars map[string]string, checkMode bool) *exec.Cmd // playbookCmdFunc mimics https://github.com/operator-framework/operator-sdk/blob/707240f006ecfc0bc86e5c21f6874d302992d598/internal/ansible/runner/runner.go#L75-L90 @@ -307,17 +318,19 @@ func (p Parameters) Init(ctx context.Context, cr *v1alpha1.AnsibleRun, behaviorV withAnsibleRunPolicy(rPolicy), // TODO should be moved to connect() func withAnsibleEnvDir(ansibleEnvDir), + withArtifactsHistoryLimit(p.ArtifactsHistoryLimit), ), nil } // Runner struct holds the configuration to run the cmdFunc type Runner struct { - Path string // absolute path on disk to a playbook or role depending on what cmdFunc expects - behaviorVars map[string]string - cmdFunc cmdFuncType // returns a Cmd that runs ansible-runner - AnsibleEnvDir string - checkMode bool - AnsibleRunPolicy *RunPolicy + Path string // absolute path on disk to a playbook or role depending on what cmdFunc expects + behaviorVars map[string]string + cmdFunc cmdFuncType // returns a Cmd that runs ansible-runner + AnsibleEnvDir string + checkMode bool + AnsibleRunPolicy *RunPolicy + artifactsHistoryLimit int } // new returns a runner that will be used as ansible-runner client @@ -345,6 +358,7 @@ func (r *Runner) Run() (*exec.Cmd, io.Reader, error) { ) dc := r.cmdFunc(r.behaviorVars, r.checkMode) + dc.Args = append(dc.Args, "--rotate-artifacts", strconv.Itoa(r.artifactsHistoryLimit)) if !r.checkMode { // for disabled checkMode dc.Stdout and dc.Stderr are respectfully // written to os.Stdout and os.Stdout for debugging purpose diff --git a/internal/controller/ansible.go b/internal/controller/ansible.go index db59bcd..2f7965e 100644 --- a/internal/controller/ansible.go +++ b/internal/controller/ansible.go @@ -28,12 +28,12 @@ import ( // Setup creates all Template controllers with the supplied logger and adds them to // the supplied manager. -func Setup(mgr ctrl.Manager, o controller.Options, ansibleCollectionsPath, ansibleRolesPath string, timeout time.Duration) error { - for _, setup := range []func(ctrl.Manager, controller.Options, string, string, time.Duration) error{ +func Setup(mgr ctrl.Manager, o controller.Options, ansibleCollectionsPath, ansibleRolesPath string, timeout time.Duration, artifactsHistoryLimit int) error { + for _, setup := range []func(ctrl.Manager, controller.Options, string, string, time.Duration, int) error{ config.Setup, ansiblerun.Setup, } { - if err := setup(mgr, o, ansibleCollectionsPath, ansibleRolesPath, timeout); err != nil { + if err := setup(mgr, o, ansibleCollectionsPath, ansibleRolesPath, timeout, artifactsHistoryLimit); err != nil { return err } } diff --git a/internal/controller/ansibleRun/ansibleRun.go b/internal/controller/ansibleRun/ansibleRun.go index 3bfb6fa..5fd293f 100644 --- a/internal/controller/ansibleRun/ansibleRun.go +++ b/internal/controller/ansibleRun/ansibleRun.go @@ -91,7 +91,7 @@ type ansibleRunner interface { } // Setup adds a controller that reconciles AnsibleRun managed resources. -func Setup(mgr ctrl.Manager, o controller.Options, ansibleCollectionsPath, ansibleRolesPath string, timeout time.Duration) error { +func Setup(mgr ctrl.Manager, o controller.Options, ansibleCollectionsPath, ansibleRolesPath string, timeout time.Duration, artifactsHistoryLimit int) error { name := managed.ControllerName(v1alpha1.AnsibleRunGroupKind) fs := afero.Afero{Fs: afero.NewOsFs()} @@ -111,11 +111,12 @@ func Setup(mgr ctrl.Manager, o controller.Options, ansibleCollectionsPath, ansib fs: fs, ansible: func(dir string) params { return ansible.Parameters{ - WorkingDirPath: dir, - GalaxyBinary: galaxyBinary, - RunnerBinary: runnerBinary, - CollectionsPath: ansibleCollectionsPath, - RolesPath: ansibleRolesPath, + WorkingDirPath: dir, + GalaxyBinary: galaxyBinary, + RunnerBinary: runnerBinary, + CollectionsPath: ansibleCollectionsPath, + RolesPath: ansibleRolesPath, + ArtifactsHistoryLimit: artifactsHistoryLimit, } }, } diff --git a/internal/controller/config/config.go b/internal/controller/config/config.go index 5e7186c..4f354a2 100644 --- a/internal/controller/config/config.go +++ b/internal/controller/config/config.go @@ -33,7 +33,7 @@ import ( // Setup adds a controller that reconciles ProviderConfigs by accounting for // their current usage. -func Setup(mgr ctrl.Manager, o controller.Options, _, _ string, _ time.Duration) error { +func Setup(mgr ctrl.Manager, o controller.Options, _, _ string, _ time.Duration, _ int) error { name := providerconfig.ControllerName(v1alpha1.ProviderConfigGroupKind) of := resource.ProviderConfigKinds{