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

Renamed meta to metadata and other cleanups #90

Merged
merged 4 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/git-using-lib/git_using_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class GitPromiseTypeModule(PromiseModule):
def __init__(self, **kwargs):
super().__init__("git_promise_module", "0.0.3", **kwargs)

def validate_promise(self, promiser, attributes, meta):
def validate_promise(self, promiser, attributes, metadata):
if not promiser.startswith("/"):
raise ValidationError(f"File path '{promiser}' must be absolute")
for name, value in attributes.items():
Expand All @@ -15,7 +15,7 @@ def validate_promise(self, promiser, attributes, meta):
if name == "repo" and type(value) is not str:
raise ValidationError(f"'repo' must be string for git promise types")

def evaluate_promise(self, promiser, attributes, meta):
def evaluate_promise(self, promiser, attributes, metadata):
folder = promiser
url = attributes["repo"]

Expand Down
4 changes: 2 additions & 2 deletions examples/gpg/gpg.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def gpg_key_present(self, homedir, user_id):
proc.communicate()
self.log_error(f"Timed out querying for gpg key '{user_id}'")

def validate_promise(self, promiser, attributes, meta):
def validate_promise(self, promiser, attributes, metadata):
if not promiser.startswith("/"):
raise ValidationError(
f"Promiser '{promiser}' for 'gpg_keys' promise must be an absolute path"
Expand All @@ -113,7 +113,7 @@ def validate_promise(self, promiser, attributes, meta):
f"Required attribute 'keylist' missing for 'gpg_keys' promise"
)

def evaluate_promise(self, promiser, attributes, meta):
def evaluate_promise(self, promiser, attributes, metadata):
keylist_json = self.clean_storejson_output(attributes["keylist"])
self.log_verbose(f"keylist_json is '{keylist_json}'")

Expand Down
4 changes: 2 additions & 2 deletions examples/rss/rss.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def __init__(self):
super().__init__("rss_promise_module", "0.0.3")


def validate_promise(self, promiser, attributes, meta):
def validate_promise(self, promiser, attributes, metadata):
# check promiser type
if type(promiser) is not str:
raise ValidationError("invalid type for promiser: expected string")
Expand Down Expand Up @@ -43,7 +43,7 @@ def validate_promise(self, promiser, attributes, meta):
raise ValidationError(f"Invalid value '{select}' for attribute select: must be newest, oldest or random")


def evaluate_promise(self, promiser, attributes, meta):
def evaluate_promise(self, promiser, attributes, metadata):
# get attriute feed
feed = attributes['feed']

Expand Down
4 changes: 2 additions & 2 deletions examples/site-up/site_up.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ class SiteUpPromiseTypeModule(PromiseModule):
def __init__(self):
super().__init__("site_up_promise_module", "0.0.2")

def validate_promise(self, promiser, attributes, meta):
def validate_promise(self, promiser, attributes, metadata):
if not self.is_url_valid(promiser):
raise ValidationError(f"URL '{promiser}' is invalid")

def evaluate_promise(self, url, attributes, meta):
def evaluate_promise(self, url, attributes, metadata):
ssl_ctx = ssl.create_default_context()
if (
"skip_ssl_verification" in attributes
Expand Down
16 changes: 16 additions & 0 deletions libraries/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
A library for CFEngine custom promise types implemented in Python.
It provides the `PromiseModule` base class and many helper values and mechanisms that facilitates creation of custom promises.

If you'd like to develop new promise types (or other modules) for CFEngine, we recommend finishing our getting started tutorial:

https://docs.cfengine.com/docs/3.21/getting-started.html
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
https://docs.cfengine.com/docs/3.21/getting-started.html
https://docs.cfengine.com/latest/getting-started.html

Maybe link to latest, lts or docs/master ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe, I did this on purpose to maybe avoid breaking links in the future.

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 always struggle to decide.


(The last part shows implementing your first module).

If you feel comfortable with using CFEngine and writing Python code already, there is a template project you can just copy and start editing:

https://github.com/cfengine/promise-type-template

For more detailed information about how custom promise types work, see our documentation:

https://docs.cfengine.com/docs/3.21/reference-promise-types-custom.html
Copy link
Member

Choose a reason for hiding this comment

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

Same here, maybe link to a not specific version

7 changes: 0 additions & 7 deletions libraries/python/README.org

This file was deleted.

16 changes: 8 additions & 8 deletions libraries/python/cfengine.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,10 +326,10 @@ def _handle_init(self):
_put_response(self._response, self._out, self._record_file)

def _handle_validate(self, promiser, attributes, request):
meta = {"promise_type": request.get("promise_type")}
metadata = {"promise_type": request.get("promise_type")}
try:
self.validate_attributes(promiser, attributes, meta)
returned = self.validate_promise(promiser, attributes, meta)
self.validate_attributes(promiser, attributes, metadata)
returned = self.validate_promise(promiser, attributes, metadata)
if returned is None:
# Good, expected
self._result = Result.VALID
Expand Down Expand Up @@ -370,9 +370,9 @@ def _handle_validate(self, promiser, attributes, request):

def _handle_evaluate(self, promiser, attributes, request):
self._result_classes = None
meta = {"promise_type": request.get("promise_type")}
metadata = {"promise_type": request.get("promise_type")}
try:
results = self.evaluate_promise(promiser, attributes, meta)
results = self.evaluate_promise(promiser, attributes, metadata)

# evaluate_promise should return either a result or a (result, result_classes) pair
if type(results) == str:
Expand Down Expand Up @@ -448,16 +448,16 @@ def prepare_promiser_and_attributes(self, promiser, attributes):
"""Override if you want to modify promiser or attributes before validate or evaluate"""
return (promiser, attributes)

def validate_attributes(self, promiser, attributes, meta):
def validate_attributes(self, promiser, attributes, metadata):
"""Override this if you want to prevent automatic validation"""
return self._validate_attributes(promiser, attributes)

def validate_promise(self, promiser, attributes, meta):
def validate_promise(self, promiser, attributes, metadata):
"""Must override this or use validation through self.add_attribute()"""
if not self._has_validation_attributes:
raise NotImplementedError("Promise module must implement validate_promise")

def evaluate_promise(self, promiser, attributes, meta):
def evaluate_promise(self, promiser, attributes, metadata):
raise NotImplementedError("Promise module must implement evaluate_promise")

def protocol_terminate(self):
Expand Down
60 changes: 26 additions & 34 deletions promise-types/ansible/README.md
Original file line number Diff line number Diff line change
@@ -1,35 +1,6 @@
# ansible promise module
The `ansible` promise type allows you to run Ansible playbooks from within CFEngine policy.

## Synopsis

* *Name*: `ansible`
* *Version*: `0.1.1`
* *Description*: Run Ansible playbooks

## Requirements

* Ansible >= 2.8.0

## Attributes

| Name | Type | Description| Mandatory | Default |
| --- | --- | --- | --- | --- |
| `playbook` | `string` | Absolute path of the Ansible playbook | No | Promiser |
| `inventory` | `string` | Absolute path of the inventory file | No | - |
| `limit` | `slist` | List of host names to target | No | `{"localhost"}` |
| `tags` | `slist` | List of tags to play | No | `{}` |
| `become` | `boolean` | Set the `become` option | No | `False` |
| `become_method` | `string` | Set the `become_method` option | No | `"sudo"` |
| `become_user` | `string` | Set the `become_user` option | No | `root` |
| `connection` | `string` | Set the `connection` option; possible values: `local`, `ssh` | No | `local` |
| `forks` | `int` | Set the `forks` option | No | `1` |
| `private_key_file` | `string` | Absolute path of the SSH private key to use | No | - |
| `remote_user` | `string` | Set the `remote_user` option | No | `root` |

## Examples

Play the `/northern.tech/playbook.yaml` playbook locally, using `/northern.tech/inventory.yaml`, and limiting
the execution to the `helloworld` tag:
For example, you can play the `/northern.tech/playbook.yaml` playbook locally, using `/northern.tech/inventory.yaml`, and limiting the execution to the `helloworld` tag:

```cfengine3
bundle agent main
Expand All @@ -42,6 +13,28 @@ bundle agent main
}
```

## Requirements

* Ansible >= 2.8.0

## Attributes

| Name | Type | Description | Mandatory | Default |
| ------------------ | --------- | ------------------------------------------------------------ | --------- | --------------- |
| `playbook` | `string` | Absolute path of the Ansible playbook | No | Promiser |
| `inventory` | `string` | Absolute path of the inventory file | No | - |
| `limit` | `slist` | List of host names to target | No | `{"localhost"}` |
| `tags` | `slist` | List of tags to play | No | `{}` |
| `become` | `boolean` | Set the `become` option | No | `False` |
| `become_method` | `string` | Set the `become_method` option | No | `"sudo"` |
| `become_user` | `string` | Set the `become_user` option | No | `root` |
| `connection` | `string` | Set the `connection` option; possible values: `local`, `ssh` | No | `local` |
| `forks` | `int` | Set the `forks` option | No | `1` |
| `private_key_file` | `string` | Absolute path of the SSH private key to use | No | - |
| `remote_user` | `string` | Set the `remote_user` option | No | `root` |

## Examples

This promise can run ansible over ssh targeting multiple hosts, for example:

```cfengine3
Expand All @@ -64,9 +57,8 @@ bundle agent main

## Authors

This software was created by the team at [Northern.tech AS](https://northern.tech), with many contributions from the community. Thanks everyone!

[CFEngine](https://cfengine.com) is sponsored by [Northern.tech AS](https://northern.tech)
This software was created by the team at [Northern.tech](https://northern.tech), with many contributions from the community.
Thanks everyone!

## Contribute

Expand Down
6 changes: 3 additions & 3 deletions promise-types/ansible/ansible_promise.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def v2_playbook_on_stats(self, stats):
class AnsiblePromiseTypeModule(PromiseModule):
def __init__(self, **kwargs):
super(AnsiblePromiseTypeModule, self).__init__(
"ansible_promise_module", "0.2.1", **kwargs
"ansible_promise_module", "0.2.2", **kwargs
)

def must_be_absolute(v):
Expand All @@ -98,12 +98,12 @@ def prepare_promiser_and_attributes(self, promiser, attributes):
safe_promiser = promiser.replace(",", "_")
return (safe_promiser, attributes)

def validate_promise(self, promiser: str, attributes: Dict, meta: Dict):
def validate_promise(self, promiser: str, attributes: Dict, metadata: Dict):
if not ANSIBLE_AVAILABLE:
raise ValidationError("Ansible Python module not available")

def evaluate_promise(
self, safe_promiser: str, attributes: Dict, meta: Dict
self, safe_promiser: str, attributes: Dict, metadata: Dict
) -> Tuple[str, List[str]]:
model = self.create_attribute_object(safe_promiser, attributes)

Expand Down
12 changes: 3 additions & 9 deletions promise-types/git/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
# git promise type

## Synopsis

* *Name*: `git`
* *Description*: Manage git checkouts of repositories to deploy files or software.
The `git` promise type enables writing concise policy for cloning a git repo and keeping it updated.

## Requirements

Expand Down Expand Up @@ -67,9 +62,8 @@ bundle agent main

## Authors

This software was created by the team at [Northern.tech AS](https://northern.tech), with many contributions from the community. Thanks everyone!

[CFEngine](https://cfengine.com) is sponsored by [Northern.tech AS](https://northern.tech)
This software was created by the team at [Northern.tech](https://northern.tech), with many contributions from the community.
Thanks everyone!

## Contribute

Expand Down
4 changes: 2 additions & 2 deletions promise-types/git/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class GitPromiseTypeModule(PromiseModule):
def __init__(self, **kwargs):
super(GitPromiseTypeModule, self).__init__(
"git_promise_module", "0.2.2", **kwargs
"git_promise_module", "0.2.3", **kwargs
)

def destination_must_be_absolute(v):
Expand Down Expand Up @@ -42,7 +42,7 @@ def depth_must_be_zero_or_more(v):
self.add_attribute("update", bool, default=True)
self.add_attribute("version", str, default="HEAD")

def evaluate_promise(self, promiser: str, attributes: Dict, meta: Dict):
def evaluate_promise(self, promiser: str, attributes: Dict, metadata: Dict):
safe_promiser = promiser.replace(",", "_")
attributes.setdefault("destination", promiser)
model = self.create_attribute_object(promiser, attributes)
Expand Down
14 changes: 4 additions & 10 deletions promise-types/groups/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
# groups promise type
The `groups` promise type helps managing local groups, letting you ensure some users are a part of a group, or excluded from a group, etc.

## Synopsis

* *Name*: `groups`
* *Version*: `0.1.3`
* *Description*: Manage local groups.
* *Note*: This is an experimental version of a promise type, and may be changed in the future.
**Note**: This is an experimental version of a promise type, and may be changed in the future.

## Requirements

Expand Down Expand Up @@ -82,9 +77,8 @@ bundle agent main

## Authors

This software was created by the team at [Northern.tech AS](https://northern.tech), with many contributions from the community. Thanks everyone!

[CFEngine](https://cfengine.com) is sponsored by [Northern.tech AS](https://northern.tech)
This software was created by the team at [Northern.tech](https://northern.tech), with many contributions from the community.
Thanks everyone!

## Contribute

Expand Down
6 changes: 3 additions & 3 deletions promise-types/groups/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

class GroupsPromiseTypeModule(PromiseModule):
def __init__(self):
super().__init__("groups_promise_module", "0.2.3")
super().__init__("groups_promise_module", "0.2.4")
self._name_regex = re.compile(r"^[a-z_][a-z0-9_-]*[$]?$")
self._name_maxlen = 32

def validate_promise(self, promiser, attributes, meta):
def validate_promise(self, promiser, attributes, metadata):
# check promiser value
if self._name_regex.match(promiser) is None:
self.log_warning(
Expand Down Expand Up @@ -115,7 +115,7 @@ def validate_promise(self, promiser, attributes, meta):
% (duplicates, promiser)
)

def evaluate_promise(self, promiser, attributes, meta):
def evaluate_promise(self, promiser, attributes, metadata):
# keep track of any repairs or failed repairs
failed_repairs = 0
repairs = 0
Expand Down
Loading