Skip to content

Commit a0c8d44

Browse files
fabianvfShawn Hurley
authored andcommitted
pkg/ansible/runner: Add ability to specify ANSIBLE_INVENTORY env variable (#1023)
**Description of the change:** If the `ANSIBLE_INVENTORY` environment variable is set, the Ansible Operator will copy it into the runner artifacts directory. This is a placeholder until the `--inventory` option to runner supports directories, or until it respects the `ansible.cfg`. **Motivation for the change:** Allows users to specify more complex inventories, should at least partially unblock #954
1 parent c5e1905 commit a0c8d44

File tree

20 files changed

+498
-11
lines changed

20 files changed

+498
-11
lines changed

hack/tests/e2e-ansible-molecule.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,16 @@ DEST_IMAGE="quay.io/example/memcached-operator:v0.0.2-test"
5050
operator-sdk build --enable-tests "$DEST_IMAGE"
5151
trap_add 'remove_prereqs' EXIT
5252
deploy_prereqs
53-
TEST_CLUSTER_PORT=25443 operator-sdk test cluster --image-pull-policy Never --namespace default --service-account memcached-operator ${DEST_IMAGE}
53+
operator-sdk test cluster --image-pull-policy Never --namespace default --service-account memcached-operator ${DEST_IMAGE}
5454

5555
remove_prereqs
5656

5757
popd
5858
popd
59+
60+
pushd "${ROOTDIR}/test/ansible-inventory"
61+
62+
sed -i 's|\(FROM quay.io/operator-framework/ansible-operator\)\(:.*\)\?|\1:dev|g' build/Dockerfile
63+
TEST_CLUSTER_PORT=24443 operator-sdk test local --namespace default
64+
65+
popd

pkg/ansible/runner/internal/inputdir/inputdir.go

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ import (
2020
"io/ioutil"
2121
"os"
2222
"path/filepath"
23+
"strings"
2324

2425
"github.com/operator-framework/operator-sdk/internal/util/fileutil"
26+
"github.com/spf13/afero"
2527

2628
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
2729
)
@@ -60,6 +62,35 @@ func (i *InputDir) addFile(path string, content []byte) error {
6062
return err
6163
}
6264

65+
// copyInventory copies a file or directory from src to dst
66+
func (i *InputDir) copyInventory(src string, dst string) error {
67+
fs := afero.NewOsFs()
68+
return afero.Walk(fs, src,
69+
func(path string, info os.FileInfo, err error) error {
70+
if err != nil {
71+
return err
72+
}
73+
fullDst := strings.Replace(path, src, dst, 1)
74+
if info.IsDir() {
75+
if err = fs.MkdirAll(fullDst, info.Mode()); err != nil {
76+
return err
77+
}
78+
} else {
79+
f, err := fs.Open(path)
80+
if err != nil {
81+
return err
82+
}
83+
if err = afero.WriteReader(fs, fullDst, f); err != nil {
84+
return err
85+
}
86+
if err = fs.Chmod(fullDst, info.Mode()); err != nil {
87+
return err
88+
}
89+
}
90+
return nil
91+
})
92+
}
93+
6394
// Stdout reads the stdout from the ansible artifact that corresponds to the
6495
// given ident and returns it as a string.
6596
func (i *InputDir) Stdout(ident string) (string, error) {
@@ -101,16 +132,39 @@ func (i *InputDir) Write() error {
101132
return err
102133
}
103134

104-
// If ansible-runner is running in a python virtual environment, propagate
105-
// that to ansible.
106-
venv := os.Getenv("VIRTUAL_ENV")
107-
hosts := "localhost ansible_connection=local"
108-
if venv != "" {
109-
hosts = fmt.Sprintf("%s ansible_python_interpreter=%s", hosts, filepath.Join(venv, "bin/python"))
110-
}
111-
err = i.addFile("inventory/hosts", []byte(hosts))
112-
if err != nil {
113-
return err
135+
// ANSIBLE_INVENTORY takes precendence over our generated hosts file
136+
// so if the envvar is set we don't bother making it, we just copy
137+
// the inventory into our runner directory
138+
ansible_inventory := os.Getenv("ANSIBLE_INVENTORY")
139+
if ansible_inventory == "" {
140+
// If ansible-runner is running in a python virtual environment, propagate
141+
// that to ansible.
142+
venv := os.Getenv("VIRTUAL_ENV")
143+
hosts := "localhost ansible_connection=local"
144+
if venv != "" {
145+
hosts = fmt.Sprintf("%s ansible_python_interpreter=%s", hosts, filepath.Join(venv, "bin/python"))
146+
}
147+
err = i.addFile("inventory/hosts", []byte(hosts))
148+
if err != nil {
149+
return err
150+
}
151+
} else {
152+
fi, err := os.Stat(ansible_inventory)
153+
if err != nil {
154+
return err
155+
}
156+
switch mode := fi.Mode(); {
157+
case mode.IsDir():
158+
err = i.copyInventory(ansible_inventory, filepath.Join(i.Path, "inventory"))
159+
if err != nil {
160+
return err
161+
}
162+
case mode.IsRegular():
163+
err = i.copyInventory(ansible_inventory, filepath.Join(i.Path, "inventory/hosts"))
164+
if err != nil {
165+
return err
166+
}
167+
}
114168
}
115169

116170
if i.PlaybookPath != "" {

test/ansible-inventory/ansible.cfg

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[defaults]
2+
inventory_plugins = /opt/ansible/plugins/inventory
3+
stdout_callback = yaml
4+
callback_whitelist = profile_tasks,timer
5+
module_utils = /opt/ansible/module_utils
6+
roles_path = /opt/ansible/roles
7+
library = /opt/ansible/library
8+
inventory = /opt/ansible/inventory
9+
filter_plugins = /opt/ansible/plugins/filter
10+
remote_tmp = /tmp/ansible
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM quay.io/operator-framework/ansible-operator:dev
2+
3+
COPY ansible.cfg /etc/ansible/ansible.cfg
4+
COPY . ${HOME}/
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: inventory.apps.fabianism.us/v1alpha1
2+
kind: Inventory
3+
metadata:
4+
name: example-inventory
5+
spec:
6+
# Add fields here
7+
size: 3
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: inventorys.inventory.apps.fabianism.us
5+
spec:
6+
group: inventory.apps.fabianism.us
7+
names:
8+
kind: Inventory
9+
listKind: InventoryList
10+
plural: inventorys
11+
singular: inventory
12+
scope: Namespaced
13+
version: v1alpha1
14+
subresources:
15+
status: {}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: inventory
5+
spec:
6+
replicas: 1
7+
selector:
8+
matchLabels:
9+
name: inventory
10+
template:
11+
metadata:
12+
labels:
13+
name: inventory
14+
spec:
15+
serviceAccountName: inventory
16+
containers:
17+
- name: inventory
18+
# Replace this with the built image name
19+
image: "{{ REPLACE_IMAGE }}"
20+
ports:
21+
- containerPort: 60000
22+
name: metrics
23+
imagePullPolicy: "{{ pull_policy|default('Always') }}"
24+
env:
25+
- name: WATCH_NAMESPACE
26+
valueFrom:
27+
fieldRef:
28+
fieldPath: metadata.namespace
29+
- name: POD_NAME
30+
valueFrom:
31+
fieldRef:
32+
fieldPath: metadata.name
33+
- name: OPERATOR_NAME
34+
value: "inventory"
35+
- name: ANSIBLE_INVENTORY
36+
value: /opt/ansible/inventory
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
apiVersion: rbac.authorization.k8s.io/v1
2+
kind: Role
3+
metadata:
4+
creationTimestamp: null
5+
name: inventory
6+
rules:
7+
- apiGroups:
8+
- ""
9+
resources:
10+
- pods
11+
- services
12+
- endpoints
13+
- persistentvolumeclaims
14+
- events
15+
- configmaps
16+
- secrets
17+
verbs:
18+
- '*'
19+
- apiGroups:
20+
- ""
21+
resources:
22+
- namespaces
23+
verbs:
24+
- get
25+
- apiGroups:
26+
- apps
27+
resources:
28+
- deployments
29+
- daemonsets
30+
- replicasets
31+
- statefulsets
32+
verbs:
33+
- '*'
34+
- apiGroups:
35+
- monitoring.coreos.com
36+
resources:
37+
- servicemonitors
38+
verbs:
39+
- get
40+
- create
41+
- apiGroups:
42+
- inventory.apps.fabianism.us
43+
resources:
44+
- '*'
45+
verbs:
46+
- '*'
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
kind: RoleBinding
2+
apiVersion: rbac.authorization.k8s.io/v1
3+
metadata:
4+
name: inventory
5+
subjects:
6+
- kind: ServiceAccount
7+
name: inventory
8+
roleRef:
9+
kind: Role
10+
name: inventory
11+
apiGroup: rbac.authorization.k8s.io
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
apiVersion: v1
2+
kind: ServiceAccount
3+
metadata:
4+
name: inventory

0 commit comments

Comments
 (0)