Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ansible INI module #88

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Ansible INI module #88

wants to merge 2 commits into from

Conversation

oleorhagen
Copy link
Contributor

@oleorhagen oleorhagen commented Jan 10, 2024

A simple custom promise module wrapping the Ansible INI custom module, and simply passing on attributes from CFEngine into the Ansible module.

The one required attribute for the module is module_path which is the path to the Ansible INI module installed on the system.

Signed-off-by: Ole Petter <ole.orhagen@northern.tech>
@olehermanse
Copy link
Member

@oleorhagen The way I see it, there are roughly 4 approaches for how to install dependencies:

  1. Dependencies are downloaded by cfbs and included as part of the deployed policy set.
  2. The hub downloads dependencies and clients fetch them from the hub.
  3. Each client downloads and installs needed dependencies for itself.
  4. Leave it up to the users to install dependencies / ensure they have them already.

Or some combination of those. All approaches could be implemented and valuable, but I lean more towards 2, or some combination of 2 and 3. They allow the hub / client to keep things up to date if desirable, and to make some choices about what is needed (version of dependencies needed).

To get the ball rolling, why not start with including some small policy to install ansible and the ini module in this CFEngine Build module?

@oleorhagen
Copy link
Contributor Author

To get the ball rolling, why not start with including some small policy to install ansible and the ini module in this CFEngine Build module?

Sounds like a good idea to me. KISS is the way for me here :p

@oleorhagen
Copy link
Contributor Author

For now I've added a cfbs.json file in the directory. However, I see all other modules are incorportated into the top-level cfbs.json. I'm guessing you want me to follow that example?

@olehermanse
Copy link
Member

For now I've added a cfbs.json file in the directory. However, I see all other modules are incorportated into the top-level cfbs.json. I'm guessing you want me to follow that example?

@oleorhagen Yea. Either that, or you can also develop the module in your own repo, if you prefer.

@@ -0,0 +1,79 @@
promise agent ini
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oleorhagen sorry that we don't have a good automatic formatter for policy language (yet). Please take a look at the style guide here and try to align with it (doesn't have to be perfect):

https://docs.cfengine.com/docs/master/examples-tutorials-writing-and-serving-policy-policy-style.html#top

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did my best. See latest push

@oleorhagen oleorhagen changed the title RFC: Ansible INI module Ansible INI module Jan 15, 2024
Copy link
Contributor

@craigcomstock craigcomstock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool! thanks for this work!

promise-types/ini/example.cf Outdated Show resolved Hide resolved
promise-types/ini/example.cf Outdated Show resolved Hide resolved

ini:
"/tmp/ini/test.toml"
module_path => "/tmp/cfe/ini_file.py",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

honestly I wouldn't want to always have to specify this path.

I would suggest moving the logic to retrieve ini_file.py into the python even though I don't like that for "visibility" sake.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't think we should have to specify module_path on the individual promise. That should be handled by setting up the promise type.

promise-types/ini/ini.py Show resolved Hide resolved
promise-types/ini/README.md Outdated Show resolved Hide resolved
promise-types/ini/README.md Show resolved Hide resolved
promise-types/ini/enable.cf Show resolved Hide resolved
promise-types/ini/example.cf Show resolved Hide resolved
promise-types/ini/example.cf Show resolved Hide resolved
promise-types/ini/example.cf Show resolved Hide resolved

ini:
"/tmp/ini/test.toml"
module_path => "/tmp/cfe/ini_file.py",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't think we should have to specify module_path on the individual promise. That should be handled by setting up the promise type.

@oleorhagen
Copy link
Contributor Author

@olehermanse feel free to have a last lookover

Copy link
Contributor

@craigcomstock craigcomstock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we must make the module_path default more dynamic based on platform/host information.

@@ -384,6 +384,9 @@ def _handle_evaluate(self, promiser, attributes, request):
except Exception as e:
self.log_critical(
"{error_type}: {error}".format(error_type=type(e).__name__, error=e)
+ e.message
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like this would read easier and fit in one line.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then again, what does black say? yeah, black seems to agree with me. Maybe run all your python files through black

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this is black. But I'm guessing it's a version thing then. I used 19. but don't know what your standard is

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh dang. the opinionated tool changes its opinions... :( I have 23.3.0 from brew on macos. Anyhow, I do like it better on one line when it fits since it is a single expression, essentially a ternary expression.

promise-types/ini/README.md Outdated Show resolved Hide resolved
promise-types/ini/example.cf Outdated Show resolved Hide resolved
promise-types/ini/ini.py Outdated Show resolved Hide resolved
promise-types/ini/ini.py Outdated Show resolved Hide resolved
if not meta.get("promise_type"):
raise ValidationError("Promise type not specified")

# TODO - does not work
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be nice to remove this or state why it doesn't work so we know what to look for when fixing.

is it important that it does not work? so we are not validating that module_path is specified?

% (promiser, attributes, meta)
)

if "module_path" not in attributes:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the TODO above where validation "does not work" here we provide a reasonable default? Doesn't seem like it actually since we are assuming here python3.11 which is a wild assumption for many different platforms.

Can we be smarter here about the path?

I had to pip3 install ansible in order to get ini_file.py. pip3 install ansible-core didn't do enough.

If I do pip3 show ansible I get an idea of where to look that is dependent on the install which might be better and something we can do programmatically via python?

? pip3 show ansible
Name: ansible
Version: 9.2.0
Summary: Radically simple IT automation
Home-page: https://ansible.com/
Author: Ansible, Inc.
Author-email: info@ansible.com
License: GPL-3.0-or-later
Location: /usr/local/lib/python3.11/site-packages
Requires: ansible-core
Required-by: 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get your point, and I agree. However, I won't have time to finish this, and it seems the other modules too write in their Readme's that the prerequisites need to be installed.

I fiddled around with how to provide this, and tried a few different things:

  1. Having the path in the promise agent ini setup, but this apparently is not valid syntax
  2. Having it in the meta section in the promise - but this does not get passed to the custom promise module (only
  3. Hardcoding it as I've done now.

Dynamically would have been the sweetest though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to pip3 install ansible in order to get ini_file.py. pip3 install ansible-core didn't do enough.

This is true, if we do not provide the file ourselves (Like in the original implementation where it was downloaded).

we could consider adding the file to the repo, and have it installed just as we do the custom promise module ini.py itself?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right on. Two things then:

  • we need to update the requirements to include ansible since that's easier than having folks have to figure out where to get it.
  • make the path dynamic with some python code if possible, doesn't have to be done by you :)

This adds a custom promise module for wrapping the existing Ansible INI module.

The module simply passes on values from the custom 'ini' promise type, to the
Ansible module.

With the example follows an example policy for downloading the required Ansible
INI module.

Signed-off-by: Ole Petter <ole.orhagen@northern.tech>
Comment on lines +11 to +13
meta:
"bundle_version" string => "0.0.1";
"promise_type" string => "ini";
Copy link
Member

@olehermanse olehermanse Feb 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the meta promise type won't do anything for the promise module.

You could use the meta attribute per promise:

  ini:
    "hello.ini"
      meta => { "report", "some=value" };

But it seems to me that the information you want to pass is more static, so would fit better if we make some room for it in the promise agent block.

Edit: This is currently not possible, the meta attribute does not get passed to the module. See custom promise type docs

Comment on lines +4 to +5
path => "$(sys.workdir)/modules/promises/ini.py";
interpreter => "/usr/bin/python3";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could enable setting environment variables for the module, or add another field of "data" to pass to the module here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I like the data field idea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants