Skip to content

Commit 73c025b

Browse files
committed
feat: alternative temp directory for generated manifests
Signed-off-by: Jonathan West <[email protected]>
1 parent 6b2984e commit 73c025b

File tree

7 files changed

+47
-17
lines changed

7 files changed

+47
-17
lines changed

pkg/cache/cluster.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"k8s.io/klog/v2/textlogger"
3535
"k8s.io/kubectl/pkg/util/openapi"
3636

37+
"github.com/argoproj/gitops-engine/pkg/utils/io"
3738
"github.com/argoproj/gitops-engine/pkg/utils/kube"
3839
"github.com/argoproj/gitops-engine/pkg/utils/tracing"
3940
)
@@ -160,8 +161,9 @@ func NewClusterCache(config *rest.Config, opts ...UpdateSettingsFunc) *clusterCa
160161
nsIndex: make(map[string]map[kube.ResourceKey]*Resource),
161162
config: config,
162163
kubectl: &kube.KubectlCmd{
163-
Log: log,
164-
Tracer: tracing.NopTracer{},
164+
Log: log,
165+
Tracer: tracing.NopTracer{},
166+
TmpPath: io.TempPathUseDevShmIfAvailable(),
165167
},
166168
syncStatus: clusterCacheSync{
167169
resyncTimeout: defaultClusterResyncTimeout,

pkg/cache/settings.go

+9
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,12 @@ func SetRespectRBAC(respectRBAC int) UpdateSettingsFunc {
170170
}
171171
}
172172
}
173+
174+
// SetTmpPath sets the path used to store temporary files that are passed to kubectl code. These temporary files are usually cluster credentials or kubernetes manifests. See 'utils/io/io.go' for details.
175+
func SetTmpPath(tmpPath string) UpdateSettingsFunc {
176+
return func(cache *clusterCache) {
177+
if kcmd, ok := cache.kubectl.(*kube.KubectlCmd); ok {
178+
kcmd.TmpPath = tmpPath
179+
}
180+
}
181+
}

pkg/engine/engine_options.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/go-logr/logr"
55
"k8s.io/klog/v2/textlogger"
66

7+
"github.com/argoproj/gitops-engine/pkg/utils/io"
78
"github.com/argoproj/gitops-engine/pkg/utils/kube"
89
"github.com/argoproj/gitops-engine/pkg/utils/tracing"
910
)
@@ -20,8 +21,9 @@ func applyOptions(opts []Option) options {
2021
o := options{
2122
log: log,
2223
kubectl: &kube.KubectlCmd{
23-
Log: log,
24-
Tracer: tracing.NopTracer{},
24+
Log: log,
25+
Tracer: tracing.NopTracer{},
26+
TmpPath: io.TempPathUseDevShmIfAvailable(),
2527
},
2628
}
2729
for _, opt := range opts {

pkg/utils/io/io.go

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
11
package io
22

3-
import (
4-
"os"
5-
)
3+
import "os"
64

75
var (
8-
// TempDir is set to '/dev/shm' if exists, otherwise is "", which defaults to os.TempDir() when passed to os.CreateTemp()
9-
TempDir string
6+
// devShmTempPath is set to '/dev/shm' if it exists, otherwise is "", which defaults to os.TempDir() when passed to os.CreateTemp()
7+
devShmTempPath string
108
)
119

1210
func init() {
1311
fileInfo, err := os.Stat("/dev/shm")
1412
if err == nil && fileInfo.IsDir() {
15-
TempDir = "/dev/shm"
13+
devShmTempPath = "/dev/shm"
1614
}
1715
}
1816

17+
// TempPathUseDevShmIfAvailable will return '/dev/shm' if it is available on the system, otherwise it will return "", which defaults to os.TempDir() when passed to os.CreateTemp()
18+
//
19+
// The result of this function is used to store temporary files that are passed to kubectl code. These temporary files are usually cluster credentials or kubernetes manifests.
20+
//
21+
// NOTE: There are tradeoffs to using this function: '/dev/shm' is backed by RAM, and thus has limited size.
22+
// - Since it is backed by RAM, this has the advantage of ensuring that sensitive data (such as credentials) are kept off disk (absent disk caching of memory)
23+
// - However, due to the limited size, '/dev/shm' may run out of disk space, and/or is more vulnerable to slow leaks of files over time.
24+
// You may instead consider using a disk-backed storage path like "", which os.CreateTemp() will default to e.g. '/tmp'.
25+
func TempPathUseDevShmIfAvailable() string {
26+
return devShmTempPath
27+
}
28+
1929
// DeleteFile is best effort deletion of a file
2030
func DeleteFile(path string) {
2131
if _, err := os.Stat(path); os.IsNotExist(err) {

pkg/utils/kube/ctl.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ type KubectlCmd struct {
4545
Log logr.Logger
4646
Tracer tracing.Tracer
4747
OnKubectlRun OnKubectlRunFunc
48+
// TmpPath is used to store temporary files that are passed to kubectl code. These temporary files are usually cluster credentials or kubernetes manifests. See 'utils/io/io.go' for details.
49+
TmpPath string
4850
}
4951

5052
type APIResourceInfo struct {
@@ -272,7 +274,7 @@ func (k *KubectlCmd) DeleteResource(ctx context.Context, config *rest.Config, gv
272274
}
273275

274276
func (k *KubectlCmd) ManageResources(config *rest.Config, openAPISchema openapi.Resources) (ResourceOperations, func(), error) {
275-
f, err := os.CreateTemp(utils.TempDir, "")
277+
f, err := os.CreateTemp(k.TmpPath, "")
276278
if err != nil {
277279
return nil, nil, fmt.Errorf("failed to generate temp file for kubeconfig: %v", err)
278280
}
@@ -293,6 +295,7 @@ func (k *KubectlCmd) ManageResources(config *rest.Config, openAPISchema openapi.
293295
tracer: k.Tracer,
294296
log: k.Log,
295297
onKubectlRun: k.OnKubectlRun,
298+
tmpPath: k.TmpPath,
296299
}, cleanup, nil
297300
}
298301

pkg/utils/kube/ctl_test.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/stretchr/testify/assert"
1111
"k8s.io/klog/v2/textlogger"
1212

13+
"github.com/argoproj/gitops-engine/pkg/utils/io"
1314
testingutils "github.com/argoproj/gitops-engine/pkg/utils/testing"
1415
"github.com/argoproj/gitops-engine/pkg/utils/tracing"
1516
)
@@ -20,8 +21,9 @@ var (
2021

2122
func TestConvertToVersion(t *testing.T) {
2223
kubectl := KubectlCmd{
23-
Log: textlogger.NewLogger(textlogger.NewConfig()),
24-
Tracer: tracing.NopTracer{},
24+
Log: textlogger.NewLogger(textlogger.NewConfig()),
25+
Tracer: tracing.NopTracer{},
26+
TmpPath: io.TempPathUseDevShmIfAvailable(),
2527
}
2628
t.Run("AppsDeployment", func(t *testing.T) {
2729
newObj, err := kubectl.ConvertToVersion(testingutils.UnstructuredFromFile("testdata/appsdeployment.yaml"), "apps", "v1")

pkg/utils/kube/resource_ops.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ type kubectlResourceOperations struct {
5252
onKubectlRun OnKubectlRunFunc
5353
fact cmdutil.Factory
5454
openAPISchema openapi.Resources
55+
// tmpPath is used to store temporary files that are passed to kubectl code. These temporary files are usually cluster credentials or kubernetes manifests. See 'utils/io/io.go' for details.
56+
tmpPath string
5557
}
5658

5759
type commandExecutor func(f cmdutil.Factory, ioStreams genericclioptions.IOStreams, fileName string) error
@@ -61,16 +63,16 @@ func (k *kubectlResourceOperations) runResourceCommand(ctx context.Context, obj
6163
if err != nil {
6264
return "", err
6365
}
64-
manifestFile, err := os.CreateTemp(io.TempDir, "")
66+
manifestFile, err := os.CreateTemp(k.tmpPath, "")
6567
if err != nil {
66-
return "", fmt.Errorf("Failed to generate temp file for manifest: %v", err)
68+
return "", fmt.Errorf("failed to generate temp file for manifest: %v", err)
6769
}
6870
defer io.DeleteFile(manifestFile.Name())
6971
if _, err = manifestFile.Write(manifestBytes); err != nil {
70-
return "", fmt.Errorf("Failed to write manifest: %v", err)
72+
return "", fmt.Errorf("failed to write manifest: %v", err)
7173
}
7274
if err = manifestFile.Close(); err != nil {
73-
return "", fmt.Errorf("Failed to close manifest: %v", err)
75+
return "", fmt.Errorf("failed to close manifest: %v", err)
7476
}
7577

7678
// log manifest

0 commit comments

Comments
 (0)