-
Notifications
You must be signed in to change notification settings - Fork 17
k8s_event module #22
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
k8s_event module #22
Conversation
27ae229
to
598f13e
Compare
plugins/modules/k8s_event.py
Outdated
return argumentSpec | ||
|
||
def execute_module(self): | ||
self.client = DynamicClient(kubernetes.config.new_client_from_config()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not going to cover enough cases, see the client construction in https://github.com/operator-framework/operator-sdk-ansible-util/blob/master/plugins/modules/k8s_status.py#L281-L342
Probably the best thing to do would be to move that function from k8s_status to a new file under module_utils, and then import it from both (you could do the same with find_resource
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still need to remove this line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
forgot to remove this line. Just did.
plugins/modules/k8s_event.py
Outdated
|
||
# Add more fields | ||
if self.params['setTimestamp']: | ||
self.params["name"] = self.params["name"] + "-" + str(now) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they usually append it with a .
rather than a -
plugins/modules/k8s_event.py
Outdated
involvedObject: | ||
type: dict | ||
description: The object that this event is about. | ||
setTimestamp: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
appendTimestamp
might be a more fitting name
plugins/modules/k8s_event.py
Outdated
setTimestamp: | ||
type: bool | ||
description: Event name should have timestamp appended to it | ||
api_key: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all these are actually documented in the auth doc fragment, see how the k8s_status module uses them (https://github.com/operator-framework/operator-sdk-ansible-util/blob/master/plugins/modules/k8s_status.py#L29-L31)
plugins/modules/k8s_event.py
Outdated
"type": self.params.get("type"), | ||
} | ||
|
||
self.exit_json(**event) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're returning without actually sending the event object to the API
3dead8d
to
8919e72
Compare
plugins/module_utils/__init__.py
Outdated
@@ -1,0 +1,88 @@ | |||
import kubernetes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd put these into a more descriptively named file, even if it's just api_utils.py
or something
plugins/modules/k8s_event.py
Outdated
extends_documentation_fragment: | ||
- operator_sdk.util.osdk_auth_options | ||
- operator_sdk.util.osdk_name_options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you want the name fragment included, that would add api_version and kind and name and namespace are double documented
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump
plugins/modules/k8s_event.py
Outdated
return argumentSpec | ||
|
||
def execute_module(self): | ||
self.client = DynamicClient(kubernetes.config.new_client_from_config()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still need to remove this line
plugins/modules/k8s_event.py
Outdated
import copy | ||
import datetime | ||
import traceback | ||
import plugins.module_utils as moduleUtils |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you'll need to import it like the other module_utils on line 176, ie
from ansible_collections.operator_sdk.util.plugins.module_utils.args_common import (AUTH_ARG_SPEC)
and it will need to be inside that try
block, which prevents the module from failing on initialization (we want them to fail on execution so that we can report the message to the user)
plugins/modules/k8s_event.py
Outdated
return argumentSpec | ||
|
||
def execute_module(self): | ||
self.client = moduleUtils.get_api_client(None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you'll want to pass self
in so that the function can pull the proper variables out of the module
08f0716
to
f848f17
Compare
plugins/modules/k8s_event.py
Outdated
instance = self.client.resources.get(api_version='v1', kind='Event') | ||
try: | ||
instance.patch(body=event) | ||
except openshift.dynamic.exceptions.NotFoundError: | ||
instance.create(body=event) | ||
|
||
return instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabianvf - Just wanted to make sure this is how the object is sent to the API. Let me know if any changes need to be made.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you'll want to return what you've documented you'll return here: https://github.com/operator-framework/operator-sdk-ansible-util/pull/22/files#diff-b2c14be32fda6eb09623e5d6d9be6350eaea5261d3c51eb8c6267fa653bc8072R131-R166
You'll also need to return whether the task resulted in a change or not (for Ansible), see the k8s_status module: https://github.com/operator-framework/operator-sdk-ansible-util/blob/master/plugins/modules/k8s_status.py#L465
so by returning instance what you're actually doing is returning the v1.Event api, what you want to return is the result of the patch
or create
. You'll also need to get
the object from the api so that you can compare it to the result of the patch
(if they are identical then you'd return changed=False
. So the logic would look more like (this is pseudocode):
v1_events = self.client.resources.get(api_version='v1', kind='Event')
try:
instance = v1_events.get(name=name, namespace=namespace)
except openshift.dynamic.exceptions.NotFoundError:
result = instance.create(body=event)
return dict(result=result.to_dict(), changed=True)
result = instance.patch(body=event)
changed = some_comparison_method(instance, result)
return dict(result=result.to_dict(), changed=changed)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, just updated the documentation return
section to match the event
object.
Also, do you you mean v1_events.create(body=event)
in the Except
block? I don't think we can reference instance
in the Except
block if it is declared in the try
block. If yes, I just made those changes.
plugins/modules/k8s_event.py
Outdated
"type": self.params.get("type"), | ||
} | ||
|
||
instance = self.client.resources.get(api_version='v1', kind='Event') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instance
is not really true, this is not an instance of an event, this is actually the api client for the v1.Event api
plugins/modules/k8s_event.py
Outdated
instance = self.client.resources.get(api_version='v1', kind='Event') | ||
try: | ||
instance.patch(body=event) | ||
except openshift.dynamic.exceptions.NotFoundError: | ||
instance.create(body=event) | ||
|
||
return instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you'll want to return what you've documented you'll return here: https://github.com/operator-framework/operator-sdk-ansible-util/pull/22/files#diff-b2c14be32fda6eb09623e5d6d9be6350eaea5261d3c51eb8c6267fa653bc8072R131-R166
You'll also need to return whether the task resulted in a change or not (for Ansible), see the k8s_status module: https://github.com/operator-framework/operator-sdk-ansible-util/blob/master/plugins/modules/k8s_status.py#L465
so by returning instance what you're actually doing is returning the v1.Event api, what you want to return is the result of the patch
or create
. You'll also need to get
the object from the api so that you can compare it to the result of the patch
(if they are identical then you'd return changed=False
. So the logic would look more like (this is pseudocode):
v1_events = self.client.resources.get(api_version='v1', kind='Event')
try:
instance = v1_events.get(name=name, namespace=namespace)
except openshift.dynamic.exceptions.NotFoundError:
result = instance.create(body=event)
return dict(result=result.to_dict(), changed=True)
result = instance.patch(body=event)
changed = some_comparison_method(instance, result)
return dict(result=result.to_dict(), changed=changed)
d5a2c28
to
77fe9fd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll also need to add some end-to-end molecule tests that exercise this module to the molecule/default
scenario (create a new task file in molecule/default/tasks
and import it from molecule/default/converge.yml
)
plugins/modules/k8s_event.py
Outdated
try: | ||
instance = v1_events.get(name=self.params.get("name"), namespace=self.params.get("namespace")) | ||
except openshift.dynamic.exceptions.NotFoundError: | ||
result = v1_events.create(body=event, namespace=self.params.get("namespace")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we'll also want to wrap the api calls in try...except blocks so we can fail gracefully
plugins/modules/k8s_event.py
Outdated
|
||
result = instance.patch(body=event, namespace=self.params.get("namespace")) | ||
changed = instance.to_dict() == result.to_dict() | ||
return dict(result=result.to_dict(), changed=changed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to_dict
is a little expensive so we should only call it once
4e81714
to
f3f1260
Compare
plugins/modules/k8s_event.py
Outdated
|
||
if self.params['appendTimestamp']: | ||
event = { | ||
"kind": "Event", | ||
"eventTime": None, | ||
"message": self.params.get("message"), | ||
"metadata": metadata, | ||
"reason": self.params.get("reason"), | ||
"reportingComponent": self.params.get("reportingComponent"), | ||
"source": self.params.get("source"), | ||
"type": self.params.get("type"), | ||
} | ||
|
||
created_event = v1_events.create(body=event, namespace=self.params.get("namespace")) | ||
return dict(result=created_event.to_dict(), changed=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabianvf - just wanted to make sure you saw this change. I created a new event and instantly returned it if the appendTimestamp
is set to true, since it'll be unique in that case.
d2aa70e
to
4d3d208
Compare
|
||
- assert: | ||
that: | ||
- event_obj.name == 'test-name' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than asserting these on the event returned by the task, you should use the community.kubernetes.k8s_info
module to retrieve the event from the API and run the asserts on that response (just to ensure the new module can't interfere with the assertions with incorrect return values or something like that)
plugins/modules/k8s_event.py
Outdated
extends_documentation_fragment: | ||
- operator_sdk.util.osdk_auth_options | ||
- operator_sdk.util.osdk_name_options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump
plugins/modules/k8s_event.py
Outdated
"name": {"type": "str", "required": True}, | ||
"namespace": {"type": "str", "required": True}, | ||
}, | ||
"api": {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this field used for?
plugins/modules/k8s_event.py
Outdated
"namespace": {"type": "str", "required": True}, | ||
}, | ||
"api": {}, | ||
"api_version": {"default": "v1"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need these fields, the only valid api_version is v1 and the only valid kind is Event
plugins/modules/k8s_event.py
Outdated
return argumentSpec | ||
|
||
def execute_module(self): | ||
self.client = DynamicClient(kubernetes.config.new_client_from_config()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bump
plugins/modules/k8s_event.py
Outdated
if self.params['appendTimestamp']: | ||
event = { | ||
"kind": "Event", | ||
"eventTime": None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably be setting this
plugins/modules/k8s_event.py
Outdated
"type": self.params.get("type"), | ||
} | ||
|
||
created_event = v1_events.create(body=event, namespace=self.params.get("namespace")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this'll need to be in a try .. except
block
plugins/modules/k8s_event.py
Outdated
event = { | ||
"kind": "Event", | ||
"count": prior_count, | ||
"eventTime": None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too
plugins/modules/k8s_event.py
Outdated
except Exception as err: | ||
self.fail_json(msg="Unable to create event: {0}".format(err)) | ||
|
||
result = v1_events.patch(body=event, namespace=self.params.get("namespace")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will also need to be in a try ... except
block
ea20b04
to
ebf4d3f
Compare
Addressed all changes, working on molecule tests now. |
c6f1e11
to
84fb24e
Compare
84fb24e
to
4c5a22d
Compare
k8s_events.py
: Allows users to more easily emit events for their managed objects.Moved the
find_resource
andget_api_client
functions fromk8s_status.py
toapi_utils.py
so that bothk8s_events.py
andk8s_status.py
can leverage those functions without redundancy.