# Operator for configuring AWX

**URL:** <https://forum.ansible.com/t/operator-for-configuring-awx/38213>\
**Category:** AWX Project\
**Tags:** awx\
**Created:** [July 11, 2023, 12:27pm UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213 "2023-07-11T12:27:41Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![iamroddo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/iamroddo/32/321_2.png) [@iamroddo](https://forum.ansible.com/u/iamroddo)\
**Post date:** [July 11, 2023, 12:27pm UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213/1 "2023-07-11T12:27:41Z")

</div>

Would an operator to maintain the projects, credentials, job templates etc in AWX be feasible? Is there an effort ongoing to create one?

---

<div class="post-metadata">

**Author:** ![Wei-Yen\_Tan](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/wei-yen_tan/32/4111_2.png) [@Wei-Yen\_Tan](https://forum.ansible.com/u/Wei-Yen_Tan)\
**Post date:** [July 11, 2023, 6:11pm UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213/2 "2023-07-11T18:11:44Z")

</div>

Not quite sure what that would look like but there already is a collection called redhat-cop controller collection that manages that for you.

[https://github.com/redhat-cop/controller\_configuration](https://github.com/redhat-cop/controller_configuration)

---

<div class="post-metadata">

**Author:** ![AWX\_Project](https://avatars.discourse-cdn.com/v4/letter/a/eada6e/32.png) [@AWX\_Project](https://forum.ansible.com/u/AWX_Project)\
**Post date:** [July 12, 2023, 6:54pm UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213/3 "2023-07-12T18:54:36Z")

</div>

This already exists here:

- [https://github.com/ansible/awx-resource-operator](https://github.com/ansible/awx-resource-operator)

That is an operator that allows you to define AWX resources as yaml that gets applied to your cluster. Then the awx-resource-operator will create those resources in your configured AWX instance. I think this is what you are referring to, please let me know if that is not the case.

Thanks,  
AWX Team

---

<div class="post-metadata">

**Author:** ![iamroddo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/iamroddo/32/321_2.png) [@iamroddo](https://forum.ansible.com/u/iamroddo)\
**Post date:** [July 13, 2023, 8:59am UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213/4 "2023-07-13T08:59:29Z")

</div>

I started playing with “awx-resource-operator” and got it working to trigger jobs. According to the README.md, it can “launch automation jobs and create job templates”, no mention of projects, inventories, credentials etc. However I see that deploying this operator deploys CRDs for projects, inventories and credentials as well as ansible jobs and job\_templates, though only those for ansible jobs and job\_templates are documented in the README.md.

I’ve been able to deploy the operator and successfully create a job template and trigger a job with it. However it fails when I attempt to create a project, with the error below.

(⎈|minikube:awx-resource-operator) awx-resource-operator $ kubectl -n awx-resource-operator logs -f job.batch/test-project  
Found 2 pods, using pod/test-project-p58hg  
[WARNING]: Unable to parse /runner/inventory as an inventory source  
[WARNING]: No inventory was parsed, only implicit localhost is available  
[WARNING]: provided hosts list is empty, only localhost is available. Note that  
the implicit localhost does not match ‘all’

PLAY [localhost] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

TASK [job\_runner : Read AnsibleJob Specs] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: raise ApiException(http\_resp=r)  
fatal: [localhost]: FAILED! =\> {“changed”: false, “module\_stderr”: “Traceback (most recent call last):\n File "/usr/local/lib/python3.8/site-packages/kubernetes/dynamic/client.py", line 55, in inner\n resp = func(self, \*args, \*\*kwargs)\n File "/usr/local/lib/python3.8/site-packages/kubernetes/dynamic/client.py", line 270, in request\n api\_response = self.client.call\_api(\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/api\_client.py", line 348, in call\_api\n return self.\_\_call\_api(resource\_path, method,\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/api\_client.py", line 180, in \_\_call\_api\n response\_data = self.request(\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/api\_client.py", line 373, in request\n return self.rest\_client.GET(url,\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 240, in GET\n return self.request("GET", url,\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 234, in request\n raise ApiException(http\_resp=r)\nkubernetes.client.exceptions.ApiException: (403)\nReason: Forbidden\nHTTP response headers: HTTPHeaderDict({‘Audit-Id’: ‘9fddb15b-2e7e-4e16-9458-872f355e52fd’, ‘Cache-Control’: ‘no-cache, private’, ‘Content-Type’: ‘application/json’, ‘X-Content-Type-Options’: ‘nosniff’, ‘X-Kubernetes-Pf-Flowschema-Uid’: ‘b9f7d140-0db8-42b5-a5d5-3718a8e0995e’, ‘X-Kubernetes-Pf-Prioritylevel-Uid’: ‘4ec9bad5-85dd-49a3-8eae-72ace7866a7a’, ‘Date’: ‘Thu, 13 Jul 2023 08:51:25 GMT’, ‘Content-Length’: ‘405’})\nHTTP response body: b’{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"[ansiblejobs.tower.ansible.com](http://ansiblejobs.tower.ansible.com) is forbidden: User \\"system:serviceaccount:awx-resource-operator:resource-operator-controller-manager-job\\" cannot list resource \\"ansiblejobs\\" in API group \\"[tower.ansible.com](http://tower.ansible.com)\\" at the cluster scope","reason":"Forbidden","details":{"group":"[tower.ansible.com](http://tower.ansible.com)","kind":"ansiblejobs"},"code":403}\n’\n\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n File "/root/.ansible/tmp/ansible-tmp-1689238282.8839157-58-279482922564523/AnsiballZ\_k8s\_info.py", line 107, in \n \_ansiballz\_main()\n File "/root/.ansible/tmp/ansible-tmp-1689238282.8839157-58-279482922564523/AnsiballZ\_k8s\_info.py", line 99, in \_ansiballz\_main\n invoke\_module(zipped\_mod, temp\_path, ANSIBALLZ\_PARAMS)\n File "/root/.ansible/tmp/ansible-tmp-1689238282.8839157-58-279482922564523/AnsiballZ\_k8s\_info.py", line 47, in invoke\_module\n runpy.run\_module(mod\_name=‘ansible\_collections.kubernetes.core.plugins.modules.k8s\_info’, init\_globals=dict(\_module\_fqn=‘ansible\_collections.kubernetes.core.plugins.modules.k8s\_info’, \_modlib\_path=modlib\_path),\n File "/usr/lib64/python3.8/runpy.py", line 207, in run\_module\n return \_run\_module\_code(code, init\_globals, run\_name, mod\_spec)\n File "/usr/lib64/python3.8/runpy.py", line 97, in \_run\_module\_code\n \_run\_code(code, mod\_globals, init\_globals,\n File "/usr/lib64/python3.8/runpy.py", line 87, in \_run\_code\n exec(code, run\_globals)\n File "/tmp/ansible\_k8s\_info\_payload\_eqx5643j/ansible\_k8s\_info\_payload.zip/ansible\_collections/kubernetes/core/plugins/modules/k8s\_info.py", line 206, in \n File "/tmp/ansible\_k8s\_info\_payload\_eqx5643j/ansible\_k8s\_info\_payload.zip/ansible\_collections/kubernetes/core/plugins/modules/k8s\_info.py", line 202, in main\n File "/tmp/ansible\_k8s\_info\_payload\_eqx5643j/ansible\_k8s\_info\_payload.zip/ansible\_collections/kubernetes/core/plugins/modules/k8s\_info.py", line 173, in execute\_module\n File "/tmp/ansible\_k8s\_info\_payload\_eqx5643j/ansible\_k8s\_info\_payload.zip/ansible\_collections/kubernetes/core/plugins/module\_utils/common.py", line 324, in kubernetes\_facts\n File "/usr/local/lib/python3.8/site-packages/kubernetes/dynamic/client.py", line 112, in get\n return self.request(‘get’, path, \*\*kwargs)\n File "/usr/local/lib/python3.8/site-packages/kubernetes/dynamic/client.py", line 57, in inner\n raise api\_exception(e)\nkubernetes.dynamic.exceptions.ForbiddenError: 403\nReason: Forbidden\nHTTP response headers: HTTPHeaderDict({‘Audit-Id’: ‘9fddb15b-2e7e-4e16-9458-872f355e52fd’, ‘Cache-Control’: ‘no-cache, private’, ‘Content-Type’: ‘application/json’, ‘X-Content-Type-Options’: ‘nosniff’, ‘X-Kubernetes-Pf-Flowschema-Uid’: ‘b9f7d140-0db8-42b5-a5d5-3718a8e0995e’, ‘X-Kubernetes-Pf-Prioritylevel-Uid’: ‘4ec9bad5-85dd-49a3-8eae-72ace7866a7a’, ‘Date’: ‘Thu, 13 Jul 2023 08:51:25 GMT’, ‘Content-Length’: ‘405’})\nHTTP response body: b’{"kind":"Status","apiVersion":"v1","metadata":{},"status":"Failure","message":"[ansiblejobs.tower.ansible.com](http://ansiblejobs.tower.ansible.com) is forbidden: User \\"system:serviceaccount:awx-resource-operator:resource-operator-controller-manager-job\\" cannot list resource \\"ansiblejobs\\" in API group \\"[tower.ansible.com](http://tower.ansible.com)\\" at the cluster scope","reason":"Forbidden","details":{"group":"[tower.ansible.com](http://tower.ansible.com)","kind":"ansiblejobs"},"code":403}\n’\nOriginal traceback: \n File "/usr/local/lib/python3.8/site-packages/kubernetes/dynamic/client.py", line 55, in inner\n resp = func(self, \*args, \*\*kwargs)\n\n File "/usr/local/lib/python3.8/site-packages/kubernetes/dynamic/client.py", line 270, in request\n api\_response = self.client.call\_api(\n\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/api\_client.py", line 348, in call\_api\n return self.\_\_call\_api(resource\_path, method,\n\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/api\_client.py", line 180, in \_\_call\_api\n response\_data = self.request(\n\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/api\_client.py", line 373, in request\n return self.rest\_client.GET(url,\n\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 240, in GET\n return self.request("GET", url,\n\n File "/usr/local/lib/python3.8/site-packages/kubernetes/client/rest.py", line 234, in request\n raise ApiException(http\_resp=r)\n\n”, “module\_stdout”: “”, “msg”: “MODULE FAILURE\nSee stdout/stderr for the exact error”, “rc”: 1}

PLAY RECAP \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
localhost

Any idea?

---

<div class="post-metadata">

**Author:** ![AWX\_Project](https://avatars.discourse-cdn.com/v4/letter/a/eada6e/32.png) [@AWX\_Project](https://forum.ansible.com/u/AWX_Project)\
**Post date:** [July 14, 2023, 6:00pm UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213/5 "2023-07-14T18:00:05Z")

</div>

the user scope error seems relevant forbidden: User \\"system:serviceaccount:awx-resource-operator:resource-operator-controller-manager-job\\" cannot list resource \\"ansiblejobs\\" in API group \\"[tower.ansible.com](http://tower.ansible.com)\\" at the cluster scope

I would start by looking into fixing these permission errors.

I’ll mention that for jobs, the operator makes calls API via awx collection, but for creating a project the operator is applying a custom resource to the k8s cluster. Hence the reason it works for jobs but not projects.

AWX Team

---

<div class="post-metadata">

**Author:** ![iamroddo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/iamroddo/32/321_2.png) [@iamroddo](https://forum.ansible.com/u/iamroddo)\
**Post date:** [July 21, 2023, 7:53am UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213/6 "2023-07-21T07:53:37Z")

</div>

Does this mean that for projects, the awx-resource-operator needs to be on the same cluster or even namespace as AWX? Is there any reason why 2 different methods, API and CRD are used for configuring these resources? I see that the operator is fairly new. Does the fact that 2 different methods are being used indicate that an experiment is going on, to determine the way forward?

---

<div class="post-metadata">

**Author:** ![AWX\_Project](https://avatars.discourse-cdn.com/v4/letter/a/eada6e/32.png) [@AWX\_Project](https://forum.ansible.com/u/AWX_Project)\
**Post date:** [July 26, 2023, 10:37pm UTC](https://forum.ansible.com/t/operator-for-configuring-awx/38213/7 "2023-07-26T22:37:34Z")

</div>

This is odd, I am not sure how CI would be passing… But I want to investigate this more. Do you mind opening an issue with this info in the awx-resource-operator repo?

- [https://github.com/ansible/awx-resource-operator/issues](https://github.com/ansible/awx-resource-operator/issues)

If I am able to reproduce, I’ll put up a fix.

Thanks,  
AWX Team
