Package: pytest-inmanta-lsm
pytest-inmanta-lsmA pytest plugin to test inmanta modules that use lsm, it is built on top ofpytest-inmantaandpytest-inmanta-extensionsInstallationpipinstallpytest-inmanta-lsmContextThis plugin is used to push code to a remote orchestrator and interact with it, via the LSM north-bound-api
It requires an LSM enabled orchestrator, with no ssl or authentication enabled, in a default setup and ssh access to the orchestrator machine, with a user that has sudo permissions.UsageFirst case: using a remote orchestratorThis plugin is built around the remote_orchestrator fixture.A typical testcase using this plugin looks as follows:deftest_full_cycle(project,remote_orchestrator):# get connection to remote_orchestratorclient=remote_orchestrator.client# setup projectproject.compile("""import quickstart""")# sync project and export service entitiesremote_orchestrator.export_service_entities()# verify the service is in the catalogresult=client.lsm_service_catalog_get_entity(remote_orchestrator.environment,SERVICE_NAME)assertresult.code==200# get a ManagedInstance object, to simplifies interacting with a specific service instanceservice_instance=remote_orchestrator.get_managed_instance(SERVICE_NAME)# create an instance and wait for it to be upservice_instance.create(attributes={"router_ip":"10.1.9.17","interface_name":"eth1","address":"10.0.0.254/24","vlan_id":14},wait_for_state="up",)# make validation fail by creating a duplicateremote_orchestrator.get_managed_instance(SERVICE_NAME).create(attributes={"router_ip":"10.1.9.17","interface_name":"eth1","address":"10.0.0.254/24","vlan_id":14},wait_for_state="rejected",)service_instance.update(attribute_updates={"vlan_id":42},wait_for_state="up",)# break it downservice_instance.delete()Second case: mocking the lsm apiThis toolbox comes with one more fixture:lsm_project.  This fixture allows to run compile using the lsm model locally.  It has as advantage that:You get a more fined grained control about what you want to see in your compile (choose the value of attributes, state, version, etc of your service).If you only care about testing one specific case it is much faster than going through the full lifecycle on the remote orchestrator.You don't need a running remote orchestrator, so you won't need to synchronize the full project anywhere.A simple usage would be as follow:deftest_model(lsm_project:lsm_project.LsmProject)->None:# Create a service object, you can modify it as you wish, depending on what you are trying to testservice=inmanta_lsm.model.ServiceInstance(id=uuid.uuid4(),environment=lsm_project.environment,service_entity="vlan-assignment",version=1,config={},state="start",candidate_attributes={"router_ip":"10.1.9.17","interface_name":"eth1","address":"10.0.0.254/24","vlan_id":14},active_attributes=None,rollback_attributes=None,created_at=datetime.datetime.now(),last_updated=datetime.datetime.now(),callback=[],deleted=False,deployment_progress=None,service_identity_attribute_value=None,)# Add the service to the mocked server.  From now on it will be taken into account# for EACH compilelsm_project.add_service(service)# Run a compile, with central focus the service we just createdlsm_project.compile("import quickstart",service_id=service.id)Options and environment variablesThe following options are available, each with a corresponding environment variable.pytest-inmanta-lsm:
  --lsm-ca-cert
                        The path to the CA certificate file used to authenticate
                        the remote orchestrator. (overrides INMANTA_LSM_CA_CERT)
  --lsm-container-env   If set to true, expect the orchestrator to be running in
                        a container without systemd.  It then assumes that all
                        environment variables required to install the modules
                        are loaded into each ssh session automatically.
                        (overrides INMANTA_LSM_CONTAINER_ENV, defaults to False)
  --lsm-ctr             If set, the fixtures will deploy and orchestrator on the
                        host, using docker (overrides INMANTA_LSM_CONTAINER,
                        defaults to False)
  --lsm-ctr-cfg-file
                        A path to a config file that should be loaded inside the
                        container a server conf. (overrides
                        INMANTA_LSM_CONTAINER_CONFIG_FILE, defaults to
                        src/pytest_inmanta_lsm/resources/my-server-
                        conf.cfg)
  --lsm-ctr-compose-file
                        The path to a docker-compose file, that should be used
                        to setup an orchestrator (overrides
                        INMANTA_LSM_CONTAINER_COMPOSE_FILE, defaults to
                        src/pytest_inmanta_lsm/resources/docker-
                        compose.yml)
  --lsm-ctr-db-version
                        The version of postgresql to use for the db of the
                        orchestrator (overrides
                        INMANTA_LSM_CONTAINER_DB_VERSION, defaults to 10)
  --lsm-ctr-env-file
                        A path to an env file that should be loaded in the
                        container. (overrides INMANTA_LSM_CONTAINER_ENV_FILE,
                        defaults to
                        src/pytest_inmanta_lsm/resources/my-env-file)
  --lsm-ctr-image
                        The container image to use for the orchestrator
                        (overrides INMANTA_LSM_CONTAINER_IMAGE, defaults to
                        containers.inmanta.com/containers/service-
                        orchestrator:4)
  --lsm-ctr-jwe-file
                        A path to an entitlement file, required by the
                        orchestrator (overrides INMANTA_LSM_CONTAINER_JWE_FILE,
                        defaults to /etc/inmanta/license/com.inmanta.jwe)
  --lsm-ctr-license-file
                        A path to a license file, required by the orchestrator
                        (overrides INMANTA_LSM_CONTAINER_LICENSE_FILE, defaults
                        to /etc/inmanta/license/com.inmanta.license)
  --lsm-ctr-pub-key-file
                        A path to a public key that should be set in the
                        container (overrides INMANTA_LSM_CONTAINER_PUB_KEY_FILE,
                        defaults to $HOME/.ssh/id_rsa.pub)
  --lsm-environment
                        The environment to use on the remote server (is created
                        if it doesn't exist) (overrides INMANTA_LSM_ENVIRONMENT,
                        defaults to 719c7ad5-6657-444b-b536-a27174cb7498)
  --lsm-host=LSM_HOST   Remote orchestrator to use for the remote_inmanta
                        fixture (overrides INMANTA_LSM_HOST, defaults to
                        127.0.0.1)
  --lsm-no-clean        Don't cleanup the orchestrator after tests (for
                        debugging purposes) (overrides INMANTA_LSM_NO_CLEAN,
                        defaults to False)
  --lsm-srv-port
                        Port the orchestrator api is listening to (overrides
                        INMANTA_LSM_SRV_PORT, defaults to 8888)
  --lsm-ssh-port
                        Port to use to ssh to the remote orchestrator (overrides
                        INMANTA_LSM_SSH_PORT, defaults to 22)
  --lsm-ssh-user
                        Username to use to ssh to the remote orchestrator
                        (overrides INMANTA_LSM_SSH_USER, defaults to centos)
  --lsm-ssl             [True | False] Choose whether to use SSL/TLS or not when
                        connecting to the remote orchestrator. (overrides
                        INMANTA_LSM_SSL, defaults to False)
  --lsm-token
                        The token used to authenticate to the remote
                        orchestrator when authentication is enabled. (overrides
                        INMANTA_LSM_TOKEN)Running testsHow the test suite is structuredThe test suite consists of two parts:The tests defined intests/test_containerized_orchestrator.pyfile always run against a container started by the test suite itself.All other tests run against the orchestrator specified by the options passed to the pytest command.Pre-requisitesTesting (and using) pytest-inmanta-lsm requires:an available orchestrator to test againstssh access to this orchestratorStepsinstall dependencies:pipinstall-rrequirements.dev.txt-rrequirements.txtpass the config for pytest-inmanta-lsm via environment variables. e.g.exportINMANTA_LSM_HOST=<theorchestrator>exportINMANTA_LSM_USER=<user>set the repo for inmanta to pull LSM fromexportINMANTA_MODULE_REPO=https://USER:LICENSE_TOKEN@modules.inmanta.com/git/inmanta-service-orchestrator/5/{}.gitInformation on how to configure a Python package repository for V2 modules, instead of a Git URL, can be foundhere.run the testspytesttestsDeploy a local orchestratorIt is possible to deploy an orchestrator locally and run the tests against it.  The orchestrator will be deployed as a container, using docker.  Here are the prerequisites in order to make it work:Havedockerinstalled on your machine.$dockerversionHave access to an orchestrator image (e.g.containers.inmanta.com/containers/service-orchestrator:4).$exportINMANTA_LSM_CONTAINER_IMAGE=containers.inmanta.com/containers/service-orchestrator:4$dockerpull$INMANTA_LSM_CONTAINER_IMAGEHave a license and an entitlement file for the orchestrator.$ls/etc/inmanta/license/com.inmanta.*/etc/inmanta/license/com.inmanta.jwe  /etc/inmanta/license/com.inmanta.license$exportINMANTA_LSM_CONTAINER_LICENSE_FILE=/etc/inmanta/license/com.inmanta.license$exportINMANTA_LSM_CONTAINER_JWE_FILE=/etc/inmanta/license/com.inmanta.jweHave a pair of private/public key to access the orchestrator.$exportPRIVATE_KEY=$HOME/.ssh/id_rsa$if[-f$PRIVATE_KEY];thenecho"Private key already exists";elsessh-keygen-trsa-b4096-f$PRIVATE_KEY-N'';fi$exportINMANTA_LSM_CONTAINER_PUB_KEY_FILE="${PRIVATE_KEY}.pub"$if[-f$INMANTA_LSM_CONTAINER_PUB_KEY_FILE];thenecho"Public key already exists";elsessh-keygen-y-f$PRIVATE_KEY>$INMANTA_LSM_CONTAINER_PUB_KEY_FILE;fiIf this is properly setup, you need to do set this option:--lsm-ctr        If set, the fixtures will deploy and orchestrator on the host, using docker (overrides INMANTA_LSM_CONTAINER, defaults to False)Then any of the other option starting withlsm-ctrprefix to configure pytest-inmanta-lsm properly.  You can specify:The path to the license and entitlement filesThe container image to useThe version of postgres to useThe public key to add in the orchestratorAny env file that should be loaded by the orchestratorA new docker-compose file to overwrite the one used by pytest-inmanta-lsm.A new server config file:warning:Some options have no effect when--lsm-ctris set.  This is the case of:--lsm-hostThe host will be overwritten with the ip of the container--lsm-srv-portThe port will be overwritten with the port the server in the container is listening to--lsm-ssh-portThe port will be22--lsm-ssh-userThe user will beinmanta--lsm-container-envThis is set to true automatically:bulb:Some options change their behavior when--lsm-ctris set.  This is the case of:--lsm-no-cleanWhen set, the docker orchestrator won't be cleaned up when the tests are done.  You will have to do it manually.