Skip to content

Commit ff65707

Browse files
authored
Scaffold a requirements.yml file for collection dependencies (#2652)
* Scaffold a requirements.yml file for collection dependencies Users will now install the operator_sdk.util and community.kubernetes collections at operator build time rather than them being baked into the base image. This allows us to put version pins to ensure compatibility of user Ansible content even when updating the base image. This should make it safer and easier for users to update to newer versions of the base image, as well as make it more transparent where the Ansible content they execute is coming from. It also allows us to push new features and bugfixes out to users via the collections without having to continually re-release the base image with new content. This will be a breaking change for existing users of the collection however. In order to continue working, users will have to add a requirements.yml to their projects and add an install step to their build/Dockerfile. * Update docs * Ensure permissions on installed collections are properly set for execution in-cluster * Update changelog and migration guide
1 parent b275ee6 commit ff65707

File tree

12 files changed

+106
-25
lines changed

12 files changed

+106
-25
lines changed

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
- Add Prometheus metrics support to Helm-based operators. ([#2603](https://github.com/operator-framework/operator-sdk/pull/2603))
1919

2020
### Changed
21-
- Ansible scaffolding has been rewritten to be simpler and make use of newer features of Ansible and Molecule.
22-
- The Kubernetes modules have migrated to the [Kubernetes Ansible collection](https://github.com/ansible-collections/kubernetes). All scaffolded code now references modules from this collection instead of Ansible Core. No immediate action is required for existing users of the modules from core, though it is recommended they switch to using the collection to continue to get non-critical bugfixes and features. The collection is now installed by default in the base image. ([#2646](https://github.com/operator-framework/operator-sdk/pull/2646))
21+
- The base image now includes version 0.10.3 of the OpenShift Python client. This should fix hanging in Python3
22+
- The Kubernetes modules have migrated to the [Kubernetes Ansible collection](https://github.com/ansible-collections/kubernetes). All scaffolded code now references modules from this collection instead of Ansible Core. No immediate action is required for existing users of the modules from core, though it is recommended they switch to using the collection to continue to get non-critical bugfixes and features. To install the collection, users will need to add the install step to their `build/Dockerfile`. New projects will have a `requirements.yml` scaffolded that includes the `community.kubernetes` collection, as well as the corresponding install step in the `build/Dockerfile`. ([#2646](https://github.com/operator-framework/operator-sdk/pull/2646))
23+
- **Breaking change** `The operator_sdk.util` collection is no longer installed by default in the base image. Existing projects will need to install it in the `build/Dockerfile`. New projects will have a `requirements.yml` scaffolded that includes the `operator_sdk.util` collection, as well as the corresponding install step in the `build/Dockerfile`. ([#2652](https://github.com/operator-framework/operator-sdk/pull/2652))
24+
- Ansible scaffolding has been rewritten to be simpler and make use of newer features of Ansible and Molecule. ([#2425](https://github.com/operator-framework/operator-sdk/pull/2425))
2325
- No longer generates the build/test-framework directory or molecule/test-cluster scenario
2426
- Adds new `cluster` scenario that can be used to test against an existing cluster
2527
- There is no longer any Ansible templating done in the `deploy/` directory, any templates used for testing will be located in `molecule/templates/` instead.

cmd/operator-sdk/migrate/cmd.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ func migrateAnsible() error {
9595
}
9696

9797
dockerfile := ansible.DockerfileHybrid{
98-
Watches: true,
99-
Roles: true,
98+
Watches: true,
99+
Roles: true,
100+
Requirements: true,
100101
}
101102
_, err := os.Stat(ansible.PlaybookYamlFile)
102103
switch {

cmd/operator-sdk/new/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ func doAnsibleScaffold() error {
268268
},
269269
&ansible.DeployOperator{},
270270
&ansible.Travis{},
271+
&ansible.RequirementsYml{},
271272
&ansible.MoleculeTestLocalMolecule{},
272273
&ansible.MoleculeTestLocalPrepare{},
273274
&ansible.MoleculeTestLocalVerify{},

doc/ansible/dev/developer_guide.md

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ Finally, a user must install the Ansible Kubernetes collection from ansible-gala
3636
$ ansible-galaxy collection install community.kubernetes
3737
```
3838

39+
Alternatively, if you've already initialized your operator, you will have a `requirements.yml`
40+
file at the top level of your project. This file specifies Ansible dependencies that
41+
need to be installed for your operator to function. By default it will install the
42+
`community.kubernetes` collection, which are used to interact with the Kubernetes API, as well
43+
as the `operator_sdk.util` collection, which provides modules and plugins for operator-specific
44+
operations. To install the Ansible modules from this file, run
45+
```bash
46+
$ ansible-galaxy collection install -r requirements.yml
47+
```
48+
3949
### Testing the k8s Ansible modules locally
4050

4151
Sometimes it is beneficial for a developer to run the Ansible code from their
@@ -50,6 +60,7 @@ Create foo-operator/tmp/build/go-test.sh
5060
Rendering Ansible Galaxy role [foo-operator/roles/Foo]...
5161
Cleaning up foo-operator/tmp/init
5262
Create foo-operator/watches.yaml
63+
Create foo-operator/requirements.yml
5364
Create foo-operator/deploy/rbac.yaml
5465
Create foo-operator/deploy/crd.yaml
5566
Create foo-operator/deploy/cr.yaml
@@ -59,8 +70,8 @@ Initialized empty Git repository in /home/dymurray/go/src/github.com/dymurray/op
5970
Run git init done
6071

6172
$ cd foo-operator
73+
$ ansible-galaxy collection install -r requirements.yml
6274
```
63-
6475
Modify `roles/Foo/tasks/main.yml` with desired Ansible logic. For this example
6576
we will create and delete a namespace with the switch of a variable:
6677
```yaml
@@ -442,19 +453,6 @@ Please look over the following sections for help debugging an Ansible Operator:
442453
* [Additional Ansible debug](../user-guide.md#additional-ansible-debug)
443454
* [Testing Ansible Operators with Molecule](testing_guide.md#testing-ansible-operators-with-molecule)
444455

445-
### Using k8s_status Ansible module with `run --local`
446-
This section covers the required steps to using the `k8s_status` Ansible module
447-
with `operator-sdk run --local`. If you are unfamiliar with managing status from
448-
the Ansible Operator, see the [proposal for user-driven status
449-
management][manage_status_proposal].
450-
451-
If your operator takes advantage of the `k8s_status` Ansible module and you are
452-
interested in testing the operator with `operator-sdk run --local`, then
453-
you will need to install the collection locally.
454-
455-
```sh
456-
$ ansible-galaxy collection install operator_sdk.util
457-
```
458456
## Extra vars sent to Ansible
459457
The extra vars that are sent to Ansible are managed by the operator. The `spec`
460458
section will pass along the key-value pairs as extra vars. This is equivalent

doc/ansible/dev/testing_guide.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ To begin, you sould have:
1515
without modification. Your top-level project structure should look like this:
1616
```
1717
.
18-
├── build
19-
├── deploy
20-
├── molecule
21-
├── roles
18+
├── build/
19+
├── deploy/
20+
├── molecule/
21+
├── roles/
2222
├── playbook.yml (optional)
23+
├── requirements.yml
2324
└── watches.yaml
2425
```
26+
- The Ansible content specified in `requirements.yml` will also need to be installed. You can install them with `ansible-galaxy collection install -r requirements.yml`
2527
2628
### Molecule scenarios
2729
If you look into the `molecule` directory, you will see four directories (`default`, `test-local`, `cluster`, `templates`).

doc/ansible/project_layout.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ After creating a new operator project using
1010
| roles/\<kind> | Contains an Ansible Role initialized using [Ansible Galaxy](https://docs.ansible.com/ansible/latest/galaxy/user_guide.html) |
1111
| build/ | Contains scripts that the `operator-sdk` uses for build and initialization. |
1212
| watches.yaml | Contains Group, Version, Kind, and the Ansible invocation method. |
13+
| requirements.yml | contains the Ansible collections and role dependencies to install during build. |
1314
| molecule/ | Contains [Molecule](https://molecule.readthedocs.io/) scenarios for end-to-end testing of your role and operator |

doc/migration/version-upgrade-guide.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,25 @@ With:
973973
- name: {{your operator name which is the value of metadata.name in this file}}
974974
```
975975

976+
#### Migration to Ansible collections
977+
978+
The core Ansible Kubernetes modules have been moved to the [`community.kubernetes` Ansible collection][kubernetes-ansible-collection]. Future development of the modules will occur there, with only critical bugfixes going into the modules in core. Additionally, the `operator_sdk.util` collection is no longer installed by default in the base image. Instead, users should add a `requirements.yml` to their project root, with the following content:
979+
980+
```yaml
981+
collections:
982+
- community.kubernetes
983+
- operator_sdk.util
984+
```
985+
986+
Users should then add the following stages to their `build/Dockerfile`:
987+
988+
```
989+
COPY requirements.yml ${HOME}/requirements.yml
990+
RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
991+
&& chmod -R ug+rwx ${HOME}/.ansible
992+
```
993+
994+
976995
[legacy-kubebuilder-doc-crd]: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
977996
[v0.8.2-go-mod]: https://github.com/operator-framework/operator-sdk/blob/28bd2b0d4fd25aa68e15d928ae09d3c18c3b51da/internal/pkg/scaffold/go_mod.go#L40-L94
978997
[activating-modules]: https://github.com/golang/go/wiki/Modules#how-to-install-and-activate-module-support
@@ -988,3 +1007,4 @@ With:
9881007
[api-rules]: https://github.com/kubernetes/kubernetes/tree/36981002246682ed7dc4de54ccc2a96c1a0cbbdb/api/api-rules
9891008
[generating-crd]: https://book.kubebuilder.io/reference/generating-crd.html
9901009
[markers]: https://book.kubebuilder.io/reference/markers.html
1010+
[kubernetes-ansible-collection]: https://github.com/ansible-collections/kubernetes

internal/scaffold/ansible/build_dockerfile.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ func (b *BuildDockerfile) GetInput() (input.Input, error) {
4646

4747
const buildDockerfileAnsibleTmpl = `FROM quay.io/operator-framework/ansible-operator:[[.ImageTag]]
4848
49+
COPY requirements.yml ${HOME}/requirements.yml
50+
RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
51+
&& chmod -R ug+rwx ${HOME}/.ansible
52+
4953
COPY watches.yaml ${HOME}/watches.yaml
5054
5155
COPY [[.RolesDir]]/ ${HOME}/[[.RolesDir]]/

internal/scaffold/ansible/dockerfilehybrid.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type DockerfileHybrid struct {
3434

3535
// Watches - if true, include a COPY statement for watches.yaml
3636
Watches bool
37+
38+
// Requirements - if true, include a COPY and RUN to install Ansible requirements
39+
Requirements bool
3740
}
3841

3942
// GetInput - gets the input
@@ -73,13 +76,12 @@ RUN yum clean all && rm -rf /var/cache/yum/* \
7376
&& pip3 install --no-cache-dir --ignore-installed ipaddress \
7477
ansible-runner==1.3.4 \
7578
ansible-runner-http==1.0.0 \
76-
openshift==0.9.2 \
79+
openshift~=0.10.0 \
7780
ansible~=2.9 \
7881
jmespath \
7982
&& yum remove -y gcc libffi-devel openssl-devel python36-devel \
8083
&& yum clean all \
81-
&& rm -rf /var/cache/yum \
82-
&& ansible-galaxy collection install operator_sdk.util community.kubernetes
84+
&& rm -rf /var/cache/yum
8385
8486
COPY build/_output/bin/[[.ProjectName]] ${OPERATOR}
8587
COPY bin /usr/local/bin
@@ -95,6 +97,10 @@ RUN TINIARCH=$(case $(arch) in x86_64) echo -n amd64 ;; ppc64le) echo -n ppc64el
9597
&& curl -L -o /tini https://github.com/krallin/tini/releases/latest/download/tini-$TINIARCH \
9698
&& chmod +x /tini
9799
100+
[[- if .Requirements ]]
101+
COPY requirements.yml ${HOME}/requirements.yml
102+
RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \
103+
&& chmod -R ug+rwx ${HOME}/.ansible[[ end ]]
98104
[[- if .Watches ]]
99105
COPY watches.yaml ${HOME}/watches.yaml[[ end ]]
100106
[[- if .Roles ]]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2020 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ansible
16+
17+
import (
18+
"github.com/operator-framework/operator-sdk/internal/scaffold/input"
19+
)
20+
21+
// RequirementsYml - A requirements file for Ansible collection dependencies
22+
type RequirementsYml struct {
23+
StaticInput
24+
}
25+
26+
// GetInput - gets the input
27+
func (r *RequirementsYml) GetInput() (input.Input, error) {
28+
if r.Path == "" {
29+
r.Path = "requirements.yml"
30+
}
31+
r.TemplateBody = requirementsYmlTmpl
32+
return r.Input, nil
33+
}
34+
35+
const requirementsYmlTmpl = `---
36+
collections:
37+
- name: community.kubernetes
38+
version: "<1.0.0"
39+
- operator_sdk.util
40+
`

0 commit comments

Comments
 (0)