Code Monkey home page Code Monkey logo

squest's Introduction

Self service portal on top of Red Hat Ansible Automation Platform

Doc Gitter Coveralls GitHub release (latest) License GitHub Repo stars

Squest is a sophisticated framework that empowers you to create a web portal offering a comprehensive Everything-as-a-Service experience.

In Squest, the services made available are not hardcoded. Instead, each service serves as a reference to your automation capabilities within the backend engine, Red Hat Ansible Automation Platform (RHAAP)/AWX (formerly known as Ansible Tower). This essentially means that anything, as long as it exists as an automation script, can be transformed into a service. Your only limitation lies in your own proficiency in automation.

Going beyond mere deployment, Squest maintains a record of every instance of services it provisions in its database. This allows you to augment these instances with additional automation, enabling your users to effectively manage the lifecycle of their resources. Each operation performed corresponds to yet another link to an automation process in the backend. This empowering feature enhances user autonomy, relieving you of the burden of providing extensive support and managing object updates.

If you want an idea of what you can do with Squest, click on the image below.

DEMO

Features

  • Service catalog:

    • Add services to your catalog based on job templates you have in your Red Hat Ansible Automation Platform/AWX instance
    • Manage requests for services (review, update, approve and process)
    • Manage lifecycle of each instance of a service
    • Integrated or external support page
    • Organization, team and user management
    • Approval workflows
    • Custom on-boarding documentation
    • RBAC (Roles, Permissions, Role bindings)
  • Resource tracking:

    • Create generic objects
    • Link objects to compose layers of your infrastructure (Physical servers, Virtualization, Containers, Projects, Tenants,...)
    • Visualize pool of resource of what you have provided (CPU, vCPU, memory, disk...)
    • Check consumptions before approving new requests
    • Graph representation of resource layers
    • Set quotas on each attribute

Links

๐Ÿ“˜ Documentation
๐Ÿ’ฌ Chat on Gitter
๐ŸŽฅ Demo video
๐Ÿต Our Ansible playbook testing framework

If you like the project, star it โญ, it motivates us a lot ๐Ÿ™‚

squest's People

Contributors

a-belhadj avatar beerfranz avatar eliasboulharts avatar gxkch avatar mwy3510 avatar sispheor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

squest's Issues

Error when creating 2 different service that use the same template name from 2 different AWX

How to reproduce:

  • Create 2 AWX/Tower instance
  • Create a service that use the "Demo job template" from AWX A
  • Create another service that use the "Demo job template" from AWX B

Traceback:

Traceback (most recent call last):
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/nico/Documents/squest/service_catalog/views/admin/catalog.py", line 20, in add_service
    if form.is_valid():
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 177, in is_valid
    return self.is_bound and not self.errors
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 172, in errors
    self.full_clean()
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 374, in full_clean
    self._clean_fields()
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 392, in _clean_fields
    value = field.clean(value)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/fields.py", line 149, in clean
    value = self.to_python(value)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/models.py", line 1274, in to_python
    value = self.queryset.get(**{key: value})
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/db/models/query.py", line 433, in get
    raise self.model.MultipleObjectsReturned(
service_catalog.models.job_templates.JobTemplate.MultipleObjectsReturned: get() returned more than one JobTemplate -- it returned 2!
ERROR 2021-07-13 13:00:37,743 log Internal Server Error: /settings/catalog/service/add_service/
Traceback (most recent call last):
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/nico/Documents/squest/service_catalog/views/admin/catalog.py", line 20, in add_service
    if form.is_valid():
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 177, in is_valid
    return self.is_bound and not self.errors
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 172, in errors
    self.full_clean()
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 374, in full_clean
    self._clean_fields()
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/forms.py", line 392, in _clean_fields
    value = field.clean(value)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/fields.py", line 149, in clean
    value = self.to_python(value)
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/forms/models.py", line 1274, in to_python
    value = self.queryset.get(**{key: value})
  File "/home/nico/.cache/pypoetry/virtualenvs/tower-service-catalog-X_7Nmek_-py3.8/lib/python3.8/site-packages/django/db/models/query.py", line 433, in get
    raise self.model.MultipleObjectsReturned(
service_catalog.models.job_templates.JobTemplate.MultipleObjectsReturned: get() returned more than one JobTemplate -- it returned 2!
[13/Jul/2021 13:00:37] "POST /settings/catalog/service/add_service/ HTTP/1.1" 500 109972

CI/CD is broken du too dependency error

We have a failure during the Docker image build

E: Failed to fetch http://security.ubuntu.com/ubuntu/pool/main/libu/libuv1/libuv1-dev_1.34.2-1ubuntu1.1_amd64.deb  404  Not Found [IP: 52.250.76.244 80]

This package has been replaced by libuv1-dev_1.34.2-1ubuntu1.3_amd64.deb.

Possible workaround

  • downloading this new package and installing it before calling the system packages installation
  • Install the package alone before (sudo apt-get install libuv1-dev)

Feature: Hook job template on request/instance state update

When creating a service, we only select the job template that will be used for provisioning.
It would be interesting to add other job templates that could be executed following the request or instance state.

  • on request submitted
  • on request canceled
  • on request need_info
  • on request processing
  • ...

And on instance change

  • on instance provisioning
  • on instance deleting
  • ...

Inconsistent mail notifications?

I have configured a service for the service catalog and the mail notifications "from" address is different:
SUBMITTED: from user that requested the service
ACCEPTED: from "admin mail address"
PROCESSING: from "admin mail address"
COMPLETED: from "squest@SQUEST_HOST"

Works as expected? I would expect that "from" should be always squest@SQUEST_HOST

Add AWX docker image to the dev Docker compose

So it can be used when dev and for integration test

  • add AWX to compose
  • Add an Ansible playbook that print extra vars sent by squest and call the squest api to update the instance (URI module)
  • Add Ansible playbook that configure AWX (create job template, create squest credential type, squest credential aka token, create Tower admin token)

Feature: user profile page

As a USER of the portal
I want to READ my profile info

Example of info:

  • email
  • first name
  • last name
  • last login
  • date created

From this page we will be able to create as well token (related to #25 )

LDAP not working

I tried different settings in ldap_config.py and also read the django docs and double check the config.
But every time I receive "AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance". Can you check this? Manually running a ldapsearch on command line works fine.

Regards,
Stephan

Wrong URL in service-delete.html

NoReverseMatch at /settings/catalog/service/4/delete/

Reverse for 'settings_catalog' not found. 'settings_catalog' is not a valid view function or pattern name.

Feature: Announcements

Admin can create an announcement message with start and end date to notify users of an incoming maintenance

Enhancement: add resource group template

As an admin
I can define a template of a resource group that can be copied to become a resource group.

E.g: define a "physical server" with CPU, Memory, Disk

Feature: Resource tracking global view

The resource tracking feature is in progress.
We have so far:

  • CRUD on resource group
  • CRUD on resource pool

We need to add a view that give a visual map of resource group with link on attributes of a resource pool.

The idea is to generate a page with graphviz.

Example of code with dot language (can be tested in the online editor here)

digraph {
  node [shape=plaintext]
    rg1 [label=
    <
    <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
      <TR>
          <TD COLSPAN="12">Resource Group</TD>
      </TR>
      <TR>
          <TD COLSPAN="6">Name</TD>
          <TD COLSPAN="6">Server</TD>
      </TR>
      <TR>
          <TD COLSPAN="6">Resource</TD>
          <TD COLSPAN="6">34</TD>
      </TR>
      <TR>
          <TD COLSPAN="12">Attributes</TD>
      </TR>
      <TR>
        <TD COLSPAN="6">Name</TD>
        <TD COLSPAN="6">Total</TD>
      </TR>
      <TR>
        <TD PORT="rg1_vCPU" COLSPAN="6">vCPU</TD>
        <TD COLSPAN="6">60</TD>
      </TR>
      <TR>
        <TD PORT="rg1_memory" COLSPAN="6">Memory</TD>
        <TD COLSPAN="6">34</TD>
      </TR>
    </TABLE>
    >
    ];
    
  node [shape=plaintext]
    rp1 [label=
    <
    <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
      <TR>
          <TD COLSPAN="12">Resource Pool</TD>
      </TR>
      <TR>
          <TD COLSPAN="6">Name</TD>
          <TD COLSPAN="6">vCenter</TD>
      </TR>
      <TR>
          <TD COLSPAN="12">Attributes</TD>
      </TR>
      <TR>
        <TD COLSPAN="3">name</TD>
        <TD COLSPAN="3">Produced</TD>
        <TD COLSPAN="3">Consumed</TD>
        <TD COLSPAN="3">Available</TD>
      </TR>
      <TR>
        <TD PORT="rp1_vCPU" COLSPAN="3">vCPU</TD>
        <TD COLSPAN="3">40</TD>
        <TD COLSPAN="3">30</TD>
        <TD COLSPAN="3">10</TD>
      </TR>
      <TR>
        <TD PORT="rp1_memory" COLSPAN="3">Memory</TD>
        <TD COLSPAN="3">100</TD>
        <TD COLSPAN="3">20</TD>
        <TD COLSPAN="3">80</TD>
      </TR>
    </TABLE>
    >
    ]; 
    
    rg2 [label=
    <
    <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
      <TR>
          <TD COLSPAN="12">Resource Group</TD>
      </TR>
      <TR>
          <TD COLSPAN="6">Name</TD>
          <TD COLSPAN="6">VM</TD>
      </TR>
      <TR>
          <TD COLSPAN="6">Resource</TD>
          <TD COLSPAN="6">34</TD>
      </TR>
      <TR>
          <TD COLSPAN="12">Attributes</TD>
      </TR>
      <TR>
        <TD COLSPAN="6">Name</TD>
        <TD COLSPAN="6">Total</TD>
      </TR>
      <TR>
        <TD PORT="rg2_vCPU" COLSPAN="6">vCPU</TD>
        <TD COLSPAN="6">60</TD>
      </TR>
      <TR>
        <TD PORT="rg2_memory" COLSPAN="6">Memory</TD>
        <TD COLSPAN="6">34</TD>
      </TR>
    </TABLE>
    >
    ];
    
    node [shape=plaintext]
    rg3 [label=
    <
    <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
      <TR>
          <TD COLSPAN="12">Resource Group</TD>
      </TR>
      <TR>
          <TD COLSPAN="3">Name</TD>
          <TD COLSPAN="3">Resources</TD>
          <TD COLSPAN="3">vCPU</TD>
          <TD COLSPAN="3">Memory</TD>
      </TR>
      <TR>
        <TD COLSPAN="3">vCenter</TD>
        <TD COLSPAN="3">23</TD>
        <TD COLSPAN="3">30</TD>
        <TD COLSPAN="3">45</TD>
      </TR>
    </TABLE>
    >
    ];
    
    rg1:rg1_vCPU -> rp1:rp1_vCPU [color = green]
    rg1:rg1_memory -> rp1:rp1_memory [color = green]
    
   rp1:rp1_vCPU  -> rg2:rg2_vCPU [color = red]
   rp1:rp1_memory -> rg2:rg2_memory [color = red]
    
}

Here is the result:
image

Todo:

  • New link from the sidebar that point to this new page
  • Method that generate the view from current data in the DB
  • Color on attribute links (red when consumer, green when producer)
  • On resource group: Link on the number of resource that point to resource_group_resource_list view
  • On resource pool: Link on producer that point to resource_pool_attribute_producer_list
  • On resource pool: Link on consumer that point to resource_pool_attribute_consumer_list
  • Add background color on TD element with same color as our bootstrap framework

Usage of day 2 operations?

How can I use day 2 operations? Do I need special extra_vars in ansible tower or in the playbook (for create/update/delete)?

Unit tests coverage > 80%

Tests to do:

  • admin/request
  • admin/tower
  • admin/catalog
  • admin/instance
  • customer/catalog
  • customer/instance
  • customer/request

Enhancement: main dashboard update

  • number of request per state
  • total instances per type of service (X number of VMware Vm, X Openshift project, X openstack tenant,...)
  • Total users
  • per billing group --> pool attribute consumption. Pie chart with consumption of each attribute for a RP if the attribute is linked to an instance and the instance to a group.
  • User with no billing group
  • Opened support cases

if RP --> attribute RG ---> Resource ---> Instance ---> Billing group THEN new category with Organization name

Feature: group and billing group management

As an admin I can:

  • CRUD on Groups

  • add/delete a user to a group

  • Create Billing Group model

  • CRUD on Billing Group

  • add / delete user from Billing Group

  • instance linked to billing group

Spec:

  • Foreign key on Instance to BillingGroup

  • User --> 1,n -- 0,n BillingGroup (create default billing group: fixtures)

  • manage the billing group of instance with survey field

When user create instance
if one billingroup
then instance billing == billingroup
else
need to select billingroup

  • describe in documentation default billing group for a new user

Bug when I process a request

Bug appear after processing a request with the "Demo job template"

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/admin/request/10/process/

Django Version: 3.1.7
Python Version: 3.8.10
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'fontawesome-free',
 'django_celery_results',
 'django_celery_beat',
 'guardian',
 'django_node_assets',
 'django_filters',
 'drf_yasg',
 'service_catalog',
 'resource_tracker']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "/home/anthony/.cache/pypoetry/virtualenvs/tower-service-catalog--Kn3-9f8-py3.8/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/anthony/.cache/pypoetry/virtualenvs/tower-service-catalog--Kn3-9f8-py3.8/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/anthony/.cache/pypoetry/virtualenvs/tower-service-catalog--Kn3-9f8-py3.8/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/anthony/HPE/squest/service_catalog/views/admin/request.py", line 162, in admin_request_process
    target_request.perform_processing()
  File "/home/anthony/.cache/pypoetry/virtualenvs/tower-service-catalog--Kn3-9f8-py3.8/lib/python3.8/site-packages/django_fsm/__init__.py", line 520, in _change_state
    return fsm_meta.field.change_state(instance, func, *args, **kwargs)
  File "/home/anthony/.cache/pypoetry/virtualenvs/tower-service-catalog--Kn3-9f8-py3.8/lib/python3.8/site-packages/django_fsm/__init__.py", line 326, in change_state
    result = method(instance, *args, **kwargs)
  File "/home/anthony/HPE/squest/service_catalog/models/request.py", line 105, in perform_processing
    tower_job_id = self.operation.job_template.execute(extra_vars=tower_extra_vars)
  File "/home/anthony/HPE/squest/service_catalog/models/job_templates.py", line 22, in execute
    return tower_job_run.id

Exception Type: AttributeError at /admin/request/10/process/
Exception Value: 'NoneType' object has no attribute 'id'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.