File: getter.go

package info (click to toggle)
docker.io 26.1.5%2Bdfsg1-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 68,576 kB
  • sloc: sh: 5,748; makefile: 912; ansic: 664; asm: 228; python: 162
file content (126 lines) | stat: -rw-r--r-- 3,894 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package template

import (
	"github.com/moby/swarmkit/v2/agent/exec"
	"github.com/moby/swarmkit/v2/api"
	"github.com/pkg/errors"
)

type templatedSecretGetter struct {
	dependencies exec.DependencyGetter
	t            *api.Task
	node         *api.NodeDescription
}

// NewTemplatedSecretGetter returns a SecretGetter that evaluates templates.
func NewTemplatedSecretGetter(dependencies exec.DependencyGetter, t *api.Task, node *api.NodeDescription) exec.SecretGetter {
	return templatedSecretGetter{dependencies: dependencies, t: t, node: node}
}

func (t templatedSecretGetter) Get(secretID string) (*api.Secret, error) {
	if t.dependencies == nil {
		return nil, errors.New("no secret provider available")
	}

	secrets := t.dependencies.Secrets()
	if secrets == nil {
		return nil, errors.New("no secret provider available")
	}

	secret, err := secrets.Get(secretID)
	if err != nil {
		return secret, err
	}

	newSpec, err := ExpandSecretSpec(secret, t.node, t.t, t.dependencies)
	if err != nil {
		return secret, errors.Wrapf(err, "failed to expand templated secret %s", secretID)
	}

	secretCopy := *secret
	secretCopy.Spec = *newSpec
	return &secretCopy, nil
}

// TemplatedConfigGetter is a ConfigGetter with an additional method to expose
// whether a config contains sensitive data.
type TemplatedConfigGetter interface {
	exec.ConfigGetter

	// GetAndFlagSecretData returns the interpolated config, and also
	// returns true if the config has been interpolated with data from a
	// secret. In this case, the config should be handled specially and
	// should not be written to disk.
	GetAndFlagSecretData(configID string) (*api.Config, bool, error)
}

type templatedConfigGetter struct {
	dependencies exec.DependencyGetter
	t            *api.Task
	node         *api.NodeDescription
}

// NewTemplatedConfigGetter returns a ConfigGetter that evaluates templates.
func NewTemplatedConfigGetter(dependencies exec.DependencyGetter, t *api.Task, node *api.NodeDescription) TemplatedConfigGetter {
	return templatedConfigGetter{dependencies: dependencies, t: t, node: node}
}

func (t templatedConfigGetter) Get(configID string) (*api.Config, error) {
	config, _, err := t.GetAndFlagSecretData(configID)
	return config, err
}

func (t templatedConfigGetter) GetAndFlagSecretData(configID string) (*api.Config, bool, error) {
	if t.dependencies == nil {
		return nil, false, errors.New("no config provider available")
	}

	configs := t.dependencies.Configs()
	if configs == nil {
		return nil, false, errors.New("no config provider available")
	}

	config, err := configs.Get(configID)
	if err != nil {
		return config, false, err
	}

	newSpec, sensitive, err := ExpandConfigSpec(config, t.node, t.t, t.dependencies)
	if err != nil {
		return config, false, errors.Wrapf(err, "failed to expand templated config %s", configID)
	}

	configCopy := *config
	configCopy.Spec = *newSpec
	return &configCopy, sensitive, nil
}

type templatedDependencyGetter struct {
	secrets exec.SecretGetter
	configs TemplatedConfigGetter
	volumes exec.VolumeGetter
}

// NewTemplatedDependencyGetter returns a DependencyGetter that evaluates templates.
func NewTemplatedDependencyGetter(dependencies exec.DependencyGetter, t *api.Task, node *api.NodeDescription) exec.DependencyGetter {
	return templatedDependencyGetter{
		secrets: NewTemplatedSecretGetter(dependencies, t, node),
		configs: NewTemplatedConfigGetter(dependencies, t, node),
		volumes: dependencies.Volumes(),
	}
}

func (t templatedDependencyGetter) Secrets() exec.SecretGetter {
	return t.secrets
}

func (t templatedDependencyGetter) Configs() exec.ConfigGetter {
	return t.configs
}

func (t templatedDependencyGetter) Volumes() exec.VolumeGetter {
	// volumes are not templated, but we include that call (and pass it
	// straight through to the underlying getter) in order to fulfill the
	// DependencyGetter interface.
	return t.volumes
}