def create_tenant(name, docker_prefix=None): """ Create a tenant via cli, record its id and token for further use. """ cli = CliTenantadm(docker_prefix) api = ApiClient(tenantadm.URL_INTERNAL) id = cli.create_tenant(name) page = 0 per_page = 20 qs_params = {} found = None while True: page = page + 1 qs_params['page'] = page qs_params['per_page'] = per_page r = api.call('GET', tenantadm.URL_INTERNAL_TENANTS, qs_params=qs_params) assert r.status_code == 200 api_tenants = r.json() found = [at for at in api_tenants if at['id'] == id] if len(found) > 0: break if len(api_tenants) == 0: break assert len(found) == 1 token = found[0]['tenant_token'] return Tenant(name, id, token)
def connected_device(env): uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}".format(uuidv4) email = "some.user+{}@example.com".format(uuidv4) u = User("", email, "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org(tname, u.name, u.pwd, plan="enterprise") update_tenant( tid, addons=["troubleshoot"], container_manager=get_container_manager(), ) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) env.new_tenant_client("mender-client", ttoken) device = MenderDevice(env.get_mender_clients()[0]) devauth.accept_devices(1) devices = devauth.get_devices_status("accepted") assert 1 == len(devices) wait_for_connect(auth, devices[0]["id"]) devconn = DeviceConnect(auth, devauth) return device, devconn
def migrate_ent_setup(): """ Migrate the ENT setup - create a tenant and user via create-org, substitute default token env in the ent. testing layer. """ ensure_conductor_ready(60, 'create_organization') u = User('', '*****@*****.**', 'correcthorse') cli = CliTenantadm(docker_prefix=docker_compose_instance) tid = cli.create_org('tenant', u.name, u.pwd) time.sleep(10) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant['tenant_token'] sed = "sed 's/$DEFAULT_TENANT_TOKEN/{}/' ".format(ttoken) + \ os.path.join(COMPOSE_FILES_PATH, "docker-compose.testing.enterprise.yml.template") + \ " > " + \ os.path.join(COMPOSE_FILES_PATH, "docker-compose.testing.enterprise.yml") subprocess.check_call(sed, shell=True) t = Tenant('tenant', tid, ttoken) t.users.append(u) return {"tenant": t}
def migrate_ent_setup(env): """ Migrate the ENT setup - create a tenant and user via create-org, substitute default token env in the ent. testing layer. """ ensure_conductor_ready(env.get_mender_conductor(), 60, 'create_organization') # extra long sleep to make sure all services ran their migrations # maybe conductor fails because some services are still in a migration phase, # and not serving the API yet? time.sleep(30) u = User('', '*****@*****.**', 'correcthorse') cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org('tenant', u.name, u.pwd) time.sleep(10) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant['tenant_token'] t = Tenant('tenant', tid, ttoken) t.users.append(u) return {"tenant": t}
def prepare_env(self, env, user_name): u = User("", user_name, "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) uuidv4 = str(uuid.uuid4()) name = "test.mender.io-" + uuidv4 tid = cli.create_org(name, u.name, u.pwd, plan="enterprise") tenant = cli.get_tenant(tid) tenant = json.loads(tenant) auth = authentication.Authentication(name=name, username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth_tenant = DeviceAuthV2(auth) mender_device = new_tenant_client(env, "test-container", tenant["tenant_token"]) mender_device.ssh_is_opened() devauth_tenant.accept_devices(1) logger.info("%s: env ready.", inspect.stack()[1].function) return mender_device
def create_org(name, username, password, plan="os"): cli = CliTenantadm() user_id = None tenant_id = cli.create_org(name, username, password, plan=plan) tenant_token = json.loads(cli.get_tenant(tenant_id))["tenant_token"] api = ApiClient(useradm.URL_MGMT) # Try log in every second for 3 minutes. # - There usually is a slight delay (in order of ms) for propagating # the created user to the db. for i in range(3 * 60): rsp = api.call("POST", useradm.URL_LOGIN, auth=(username, password)) if rsp.status_code == 200: break time.sleep(1) if rsp.status_code != 200: raise ValueError( "User could not log in within three minutes after organization has been created." ) user_token = rsp.text rsp = api.with_auth(user_token).call("GET", useradm.URL_USERS) users = json.loads(rsp.text) for user in users: if user["email"] == username: user_id = user["id"] break if user_id == None: raise ValueError("Error retrieving user id.") tenant = Tenant(name, tenant_id, tenant_token) user = User(user_id, username, password) tenant.users.append(user) return tenant
def clean_migrated_mongo(clean_mongo): useradm_cli = CliUseradm() tenantadm_cli = CliTenantadm() for t in ['tenant1', 'tenant2']: useradm_cli.migrate(t) tenantadm_cli.migrate() yield clean_mongo
def clean_migrated_mongo_mt(clean_mongo): deviceauth_cli = CliDeviceauth() useradm_cli = CliUseradm() tenantadm_cli = CliTenantadm() for t in ["tenant1", "tenant2"]: deviceauth_cli.migrate(t) useradm_cli.migrate(t) tenantadm_cli.migrate() yield clean_mongo
def create_org( name: str, username: str, password: str, plan: str = "os", containers_namespace: str = "backend-tests", container_manager=None, ) -> Tenant: cli = CliTenantadm( containers_namespace=containers_namespace, container_manager=container_manager ) user_id = None tenant_id = cli.create_org(name, username, password, plan=plan) tenant_token = json.loads(cli.get_tenant(tenant_id))["tenant_token"] host = GATEWAY_HOSTNAME if container_manager is not None: host = container_manager.get_mender_gateway() api = ApiClient(useradm.URL_MGMT, host=host) # Try log in every second for 3 minutes. # - There usually is a slight delay (in order of ms) for propagating # the created user to the db. for i in range(3 * 60): rsp = api.call("POST", useradm.URL_LOGIN, auth=(username, password)) if rsp.status_code == 200: break time.sleep(1) assert ( rsp.status_code == 200 ), "User could not log in within three minutes after organization has been created." user_token = rsp.text rsp = api.with_auth(user_token).call("GET", useradm.URL_USERS) users = json.loads(rsp.text) for user in users: if user["email"] == username: user_id = user["id"] break if user_id is None: raise ValueError("Error retrieving user id.") tenant = Tenant(name, tenant_id, tenant_token) user = User(user_id, username, password) user.token = user_token tenant.users.append(user) return tenant
def _make_tenant(self, plan, env): tname = "tenant-{}".format(plan) email = "user@{}.com".format(tname) cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org(tname, email, "correcthorse", plan) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] # the cli now sets all addons to 'enabled' - # disable them for initial 'all disabled' state update_tenant( tenant["id"], addons=[], container_manager=get_container_manager(), ) auth = Authentication(name=tname, username=email, password="******") auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) env.new_tenant_client("test-container-{}".format(plan), ttoken) device = MenderDevice(env.get_mender_clients()[0]) devauth.accept_devices(1) devices = list( set([ device["id"] for device in devauth.get_devices_status("accepted") ])) assert 1 == len(devices) tenant = Tenant(tname, tid, ttoken) u = User("", email, "correcthorse") tenant.users.append(u) tenant.device = device tenant.device_id = devices[0] tenant.auth = auth tenant.devauth = devauth return tenant
def test_filetransfer(self, enterprise_no_client): u = User("", "*****@*****.**", "whatsupdoc") cli = CliTenantadm(containers_namespace=enterprise_no_client.name) tid = cli.create_org("os-tenant", u.name, u.pwd, plan="os") # FT requires "troubleshoot" update_tenant( tid, addons=["troubleshoot"], container_manager=get_container_manager(), ) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) auth = authentication.Authentication(name="os-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth_tenant = DeviceAuthV2(auth) enterprise_no_client.new_tenant_client("configuration-test-container", tenant["tenant_token"]) mender_device = MenderDevice( enterprise_no_client.get_mender_clients()[0]) mender_device.ssh_is_opened() devauth_tenant.accept_devices(1) devices = list( set([ device["id"] for device in devauth_tenant.get_devices_status("accepted") ])) assert 1 == len(devices) wait_for_connect(auth, devices[0]) authtoken = auth.get_auth_token() super().test_filetransfer(devices[0], authtoken, content_assertion="ServerURL")
def create_tenant(env): uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}".format(uuidv4) email = "some.user+{}@example.com".format(uuidv4) u = User("", email, "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org(tname, u.name, u.pwd, plan="os") tenant = cli.get_tenant(tid.strip()) tenant = json.loads(tenant) env.tenant = tenant auth = authentication.Authentication(name="os-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() env.auth = auth return tenant
def prepare_env_for_connect(env): uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}".format(uuidv4) email = "some.user+{}@example.com".format(uuidv4) u = User("", email, "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org(tname, u.name, u.pwd, plan="os") # FT requires "troubleshoot" update_tenant( tid, addons=["troubleshoot"], container_manager=get_container_manager(), ) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) env.tenant = tenant auth = authentication.Authentication(name="os-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth_tenant = DeviceAuthV2(auth) mender_device = new_tenant_client(env, "mender-client", tenant["tenant_token"]) mender_device.ssh_is_opened() devauth_tenant.accept_devices(1) devices = devauth_tenant.get_devices_status("accepted") assert 1 == len(devices) devid = devices[0]["id"] authtoken = auth.get_auth_token() wait_for_connect(auth, devid) return devid, authtoken, auth, mender_device
def prepare_env(self, env, user_name): u = User("", user_name, "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org("monitor-tenant", u.name, u.pwd, plan="enterprise") # at the moment we do not have a notion of a monitor add-on in the # backend, but this will be needed here, see MEN-4809 # update_tenant( # tid, addons=["monitor"], container_manager=get_container_manager(), # ) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) auth = authentication.Authentication( name="monitor-tenant", username=u.name, password=u.pwd ) auth.create_org = False auth.reset_auth_token() devauth_tenant = DeviceAuthV2(auth) env.new_tenant_client("configuration-test-container", tenant["tenant_token"]) env.device = mender_device = MenderDevice(env.get_mender_clients()[0]) mender_device.ssh_is_opened() devauth_tenant.accept_devices(1) devices = list( set( [ device["id"] for device in devauth_tenant.get_devices_status("accepted") ] ) ) assert 1 == len(devices) devid = devices[0] authtoken = auth.get_auth_token() return devid, authtoken, auth, mender_device
def tenants_users(clean_migrated_mongo_mt): cli = CliTenantadm() api = ApiClient(tenantadm.URL_INTERNAL) names = ["tenant1", "tenant2"] tenants = [] for n in names: username = "******" % n password = "******" tenant = create_org(n, username, password) yield tenants
def tenants_users(clean_migrated_mongo): tenants = [] cli = CliTenantadm() api = ApiClient(tenantadm.URL_INTERNAL) for n in ["tenant1", "tenant2"]: username = "******" # user[12]@tenant[12].com password = "******" # Create tenant with two users tenant = create_org(n, username % (1, n), "123password", plan="enterprise") tenant.users.append(create_user(username % (2, n), password, tenant.id)) tenants.append(tenant) yield tenants
def connected_device(self, env): u = User("", "*****@*****.**", "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org("enterprise-tenant", u.name, u.pwd, "enterprise") update_tenant( tid, addons=["troubleshoot"], container_manager=get_container_manager(), ) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) env.new_tenant_client("configuration-test-container", ttoken) device = MenderDevice(env.get_mender_clients()[0]) devauth.accept_devices(1) devices = list( set([ device["id"] for device in devauth.get_devices_status("accepted") ])) assert 1 == len(devices) wait_for_connect(auth, devices[0]) devconn = DeviceConnect(auth, devauth) return device, devconn
def tenants_users(clean_migrated_mongo_mt): cli = CliTenantadm() api = ApiClient(tenantadm.URL_INTERNAL) names = ['tenant1', 'tenant2'] tenants = [] for n in names: tenants.append(create_tenant(n)) for t in tenants: for i in range(2): user = create_tenant_user(i, t) t.users.append(user) yield tenants
def test_update_control_with_broken_map( self, enterprise_no_client, valid_image, ): """ Schedule an update with an invalid map, which should fail. """ uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}".format(uuidv4) email = "some.user+{}@example.com".format(uuidv4) u = User("", email, "whatsupdoc") cli = CliTenantadm(containers_namespace=enterprise_no_client.name) tid = cli.create_org(tname, u.name, u.pwd, plan="enterprise") tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) new_tenant_client(enterprise_no_client, "mender-client", ttoken) devauth.accept_devices(1) deploy = Deployments(auth, devauth) devices = list( set([ device["id"] for device in devauth.get_devices_status("accepted") ])) assert 1 == len(devices) with tempfile.NamedTemporaryFile() as artifact_file: image.make_rootfs_artifact( valid_image, conftest.machine_name, "test-update-control", artifact_file.name, ) deploy.upload_image(artifact_file.name, description="control map update test") deployment_id = deploy.trigger_deployment( name="New valid update", artifact_name="test-update-control", devices=devices, update_control_map={ "Priority": 1, "States": { "BogusState_Enter": { "action": "pause" } }, }, ) # Query the deployment, and verify that the map returned contains the # deployment ID res_json = deploy.get_deployment(deployment_id) assert deployment_id == res_json.get("update_control_map").get( "id"), res_json # Wait for the device to reject it and fail. deploy.check_expected_status("finished", deployment_id) deploy.check_expected_statistics(deployment_id, "failure", 1)
def _create_org(self, name, username, password, plan="os"): namespace = get_container_manager().name cli = CliTenantadm(containers_namespace=namespace) tenant_id = cli.create_org(name, username, password, plan) return tenant_id
def test_deployment_retry_failed_update(self, enterprise_no_client): """Tests that a client installing a deployment created with a retry limit This is done through setting up a new tenant on the enterprise plan, with a device bootstrapped to the tenant. Then an Artifact is created which contains a script, for the script update module. The script will store a retry-count in a temp-file on the device, and fail, as long as the retry-count < 3. On the third go, the script will, pass, and along with it, so should the update. """ env = enterprise_no_client # Create an enterprise plan tenant u = User("", "*****@*****.**", "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org("enterprise-tenant", u.name, u.pwd, plan="enterprise") tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] logger.info(f"tenant json: {tenant}") tenant = Tenant("tenant", tid, ttoken) tenant.users.append(u) # And authorize the user to the tenant account auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) deploy = Deployments(auth, devauth) # Add a client to the tenant enterprise_no_client.new_tenant_client("retry-test-container", tenant.tenant_token) devauth.accept_devices(1) device = MenderDevice(env.get_mender_clients()[0]) with tempfile.NamedTemporaryFile() as tf: artifact = make_script_artifact("retry-artifact", conftest.machine_name, tf.name) deploy.upload_image(artifact) devices = list( set([ device["id"] for device in devauth.get_devices_status("accepted") ])) assert len(devices) == 1 deployment_id = deploy.trigger_deployment( "retry-test", artifact_name="retry-artifact", devices=devices, retries=3) logger.info(deploy.get_deployment(deployment_id)) # Now just wait for the update to succeed deploy.check_expected_statistics(deployment_id, "success", 1) deploy.check_expected_status("finished", deployment_id) # Verify the update was actually installed on the device out = device.run("mender -show-artifact").strip() assert out == "retry-artifact" # Verify the number of attempts taken to install the update out = device.run("cat /tmp/retry-attempts").strip() assert out == "3"
def _make_trial_tenant(self, env): uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}-{}".format(uuidv4, "trial") email = "some.user+{}@example.com".format(uuidv4) tadmm = ApiClient( host=get_container_manager().get_mender_gateway(), base_url=tenantadm_v2.URL_MGMT, ) args = { "organization": tname, "email": email, "password": "******", "name": "foo", "g-recaptcha-response": "dummy", "plan": "enterprise", } res = tadmm.call("POST", tenantadm_v2.URL_CREATE_ORG_TRIAL, body=args,) assert res.status_code == 202 # get tenant id tenantadm_host = ( tenantadm.HOST if isK8S() else get_container_manager().get_ip_of_service("mender-tenantadm")[0] + ":8080" ) tadmi = ApiClient( host=tenantadm_host, base_url=tenantadm.URL_INTERNAL, schema="http://", ) res = tadmi.call( "GET", tenantadm.URL_INTERNAL_TENANTS, qs_params={"username": email} ) assert res.status_code == 200 assert len(res.json()) == 1 apitenant = res.json()[0] cli = CliTenantadm(containers_namespace=env.name) tenant = cli.get_tenant(apitenant["id"]) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] auth = Authentication(name=tname, username=email, password="******") auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) new_tenant_client(env, "mender-client-trial", ttoken) devauth.accept_devices(1) devices = list( set([device["id"] for device in devauth.get_devices_status("accepted")]) ) assert 1 == len(devices) tenant = Tenant(tname, apitenant["id"], ttoken) u = User("", email, "correcthorse") tenant.users.append(u) tenant.device_id = devices[0] tenant.auth = auth tenant.devauth = devauth return tenant
def _get_tenant_data(self, tenant_id): namespace = get_container_manager().name cli = CliTenantadm(containers_namespace=namespace) tenant = cli.get_tenant(tenant_id) return tenant
def create_org(name, user, password): cli = CliTenantadm() return cli.create_org(name, user, password)
def test_update_control_with_expiring_control_map( self, enterprise_no_client, valid_image_with_mender_conf, ): """Run an update, in which the download stage takes longer than the expiry time of the control map. In other words, test MEN-5096. This is done by having an Artifact script pause in Download for a time longer than the UpdateControlMapExpiration time. This will only pass if the client renewes the control map. """ user_name = "ci.email.tests+{}@mender.io".format(str(uuid.uuid4())) u = User("", user_name, "whatsupdoc") cli = CliTenantadm(containers_namespace=enterprise_no_client.name) tid = cli.create_org("enterprise-tenant", u.name, u.pwd, "enterprise") tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) device = new_tenant_client(enterprise_no_client, "mender-client", ttoken) devauth.accept_devices(1) deploy = Deployments(auth, devauth) devices = list( set([ device["id"] for device in devauth.get_devices_status("accepted") ])) assert 1 == len(devices) mender_conf = device.run("cat /etc/mender/mender.conf") with tempfile.NamedTemporaryFile(prefix="Download_Leave_01_", mode="w") as sleep_script: expiration = int( json.loads(mender_conf) ["UpdateControlMapExpirationTimeSeconds"]) sleep_script.writelines( ["#! /bin/bash\n", "sleep {}".format(expiration + 60)]) sleep_script.flush() os.fchmod(sleep_script.fileno(), 0o0755) device.put( os.path.basename(sleep_script.name), local_path=os.path.dirname(sleep_script.name), remote_path="/etc/mender/scripts/", ) with tempfile.NamedTemporaryFile() as artifact_file: created_artifact = image.make_rootfs_artifact( valid_image_with_mender_conf(mender_conf), conftest.machine_name, "test-update-control", artifact_file.name, ) deploy.upload_image(artifact_file.name, description="control map update test") deployment_id = deploy.trigger_deployment( name="New valid update", artifact_name="test-update-control", devices=devices, update_control_map={ "Priority": 1, "States": { "ArtifactInstall_Enter": { "action": "pause", }, }, }, ) # Query the deployment, and verify that the map returned contains the # deployment ID res_json = deploy.get_deployment(deployment_id) assert deployment_id == res_json.get("update_control_map").get( "id"), res_json deploy.check_expected_statistics(deployment_id, "pause_before_installing", 1) deploy.patch_deployment( deployment_id, update_control_map={ "Priority": 2, "States": { "ArtifactInstall_Enter": { "action": "force_continue", }, }, }, ) deploy.check_expected_status("finished", deployment_id) deploy.check_expected_statistics(deployment_id, "success", 1)
def clean_migrated_mongo(clean_mongo): tenantadm_cli = CliTenantadm() tenantadm_cli.migrate() yield clean_mongo
def test_configuration(self, enterprise_no_client): """Tests the deployment and reporting of the configuration The tests set the configuration of a device and verifies the new configuration is reported back to the back-end. """ env = enterprise_no_client # Create an enterprise plan tenant uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}".format(uuidv4) email = "some.user+{}@example.com".format(uuidv4) u = User("", email, "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org(tname, u.name, u.pwd, plan="enterprise") # what we really need is "configure" # but for trigger tests we're also checking device avail. in "deviceconnect" # so add "troubleshoot" as well update_tenant( tid, addons=["configure", "troubleshoot"], container_manager=get_container_manager(), ) tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] logger.info(f"tenant json: {tenant}") tenant = Tenant("tenant", tid, ttoken) tenant.users.append(u) # And authorize the user to the tenant account auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth_tenant = DeviceAuthV2(auth) # Add a client to the tenant mender_device = new_tenant_client(enterprise_no_client, "mender-client", tenant.tenant_token) mender_device.ssh_is_opened() devauth_tenant.accept_devices(1) # list of devices devices = list( set([ device["id"] for device in devauth_tenant.get_devices_status("accepted") ])) assert 1 == len(devices) wait_for_connect(auth, devices[0]) # set and verify the device's configuration # retry to skip possible race conditions between update poll and update trigger for _ in redo.retrier(attempts=3, sleeptime=1): set_and_verify_config({"key": "value"}, devices[0], auth.get_auth_token()) forced = was_update_forced(mender_device) if forced: return assert False, "the update check was never triggered"
def test_update_control_limit( self, enterprise_no_client, valid_image_with_mender_conf, ): """MEN-5421: Test that the client gracefully handles being rate-limited by the Mender server. Set the rate-limit to 1 request/ 60 seconds for the deployments/next endpoint, then schedule an update with a pause in ArtifactReboot_Enter only, then continue, after the client has reported the paused substate back to the server, all the way until the deployment is successfully finished. """ uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}".format(uuidv4) email = "some.user+{}@example.com".format(uuidv4) u = User("", email, "whatsupdoc") cli = CliTenantadm(containers_namespace=enterprise_no_client.name) tid = cli.create_org(tname, u.name, u.pwd, plan="enterprise") # Rate-limit the /deployments/next endpoint tc = ApiClient( tenantadm.URL_INTERNAL, host=get_container_manager().get_ip_of_service("mender-tenantadm") [0] + ":8080", schema="http://", ) r = tc.call( "PUT", tenantadm.URL_INTERNAL_TENANTS + "/" + tid, body={ "api_limits": { "devices": { "bursts": [{ "action": "POST", "uri": "/api/devices/v2/deployments/device/deployments/next", "min_interval_sec": 60, }], } } }, ) assert r.ok, "Failed to set the rate-limit on the 'deployements/next' endpoint" time.sleep(10) r = tc.call( "GET", tenantadm.URL_INTERNAL_TENANTS + "/" + tid, ) resp_json = r.json() if (resp_json.get("api_limits", {}).get("devices", {}).get( "bursts", [{}])[0].get("min_interval_sec") != 60): pytest.fail("rate limits not enabled. The test is invalid") tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) device = new_tenant_client(enterprise_no_client, "mender-client", ttoken) devauth.accept_devices(1) deploy = Deployments(auth, devauth) devices = list( set([ device["id"] for device in devauth.get_devices_status("accepted") ])) assert 1 == len(devices) mender_conf = device.run("cat /etc/mender/mender.conf") with tempfile.NamedTemporaryFile() as artifact_file: image.make_rootfs_artifact( valid_image_with_mender_conf(mender_conf), conftest.machine_name, "test-update-control", artifact_file.name, ) deploy.upload_image(artifact_file.name, description="control map update test") deployment_id = deploy.trigger_deployment( name="New valid update", artifact_name="test-update-control", devices=devices, update_control_map={ "Priority": 1, "States": { "ArtifactReboot_Enter": { "action": "pause" } }, }, ) # Query the deployment, and verify that the map returned contains the # deployment ID res_json = deploy.get_deployment(deployment_id) assert deployment_id == res_json.get("update_control_map").get( "id"), res_json # Wait for the device to pause in ArtifactInstall deploy.check_expected_statistics(deployment_id, "pause_before_rebooting", 1) deploy.patch_deployment( deployment_id, update_control_map={ "Priority": 2, "States": { "ArtifactReboot_Enter": { "action": "force_continue" }, }, }, ) deploy.check_expected_status("finished", deployment_id) deploy.check_expected_statistics(deployment_id, "success", 1)
def test_configuration(self, enterprise_no_client): """Tests the deployment and reporting of the configuration The tests set the configuration of a device and verifies the new configuration is reported back to the back-end. """ env = enterprise_no_client # Create an enterprise plan tenant u = User("", "*****@*****.**", "whatsupdoc") cli = CliTenantadm(containers_namespace=env.name) tid = cli.create_org("enterprise-tenant", u.name, u.pwd, plan="enterprise") tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] logger.info(f"tenant json: {tenant}") tenant = Tenant("tenant", tid, ttoken) tenant.users.append(u) # And authorize the user to the tenant account auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth_tenant = DeviceAuthV2(auth) # Add a client to the tenant enterprise_no_client.new_tenant_client("configuration-test-container", tenant.tenant_token) mender_device = MenderDevice( enterprise_no_client.get_mender_clients()[0]) mender_device.ssh_is_opened() devauth_tenant.accept_devices(1) # list of devices devices = list( set([ device["id"] for device in devauth_tenant.get_devices_status("accepted") ])) assert 1 == len(devices) wait_for_connect(auth, devices[0]) # set and verify the device's configuration # retry to skip possible race conditions between update poll and update trigger for _ in redo.retrier(attempts=3, sleeptime=1): set_and_verify_config({"key": "value"}, devices[0], auth.get_auth_token()) forced = was_update_forced(mender_device) if forced: return assert False, "the update check was never triggered"
def test_update_control( self, enterprise_no_client, valid_image_with_mender_conf, ): """ Schedule an update with a pause in ArtifactInstall_Enter, ArtifactReboot_Enter, and ArtifactCommit_Enter, then continue, after the client has reported the paused substate back to the server, all the way until the deployment is successfully finished. """ uuidv4 = str(uuid.uuid4()) tname = "test.mender.io-{}".format(uuidv4) email = "some.user+{}@example.com".format(uuidv4) u = User("", email, "whatsupdoc") cli = CliTenantadm(containers_namespace=enterprise_no_client.name) tid = cli.create_org(tname, u.name, u.pwd, plan="enterprise") tenant = cli.get_tenant(tid) tenant = json.loads(tenant) ttoken = tenant["tenant_token"] auth = Authentication(name="enterprise-tenant", username=u.name, password=u.pwd) auth.create_org = False auth.reset_auth_token() devauth = DeviceAuthV2(auth) device = new_tenant_client(enterprise_no_client, "mender-client", ttoken) devauth.accept_devices(1) deploy = Deployments(auth, devauth) devices = list( set([ device["id"] for device in devauth.get_devices_status("accepted") ])) assert 1 == len(devices) mender_conf = device.run("cat /etc/mender/mender.conf") with tempfile.NamedTemporaryFile() as artifact_file: image.make_rootfs_artifact( valid_image_with_mender_conf(mender_conf), conftest.machine_name, "test-update-control", artifact_file.name, ) deploy.upload_image(artifact_file.name, description="control map update test") deployment_id = deploy.trigger_deployment( name="New valid update", artifact_name="test-update-control", devices=devices, update_control_map={ "Priority": 1, "States": { "ArtifactInstall_Enter": { "action": "pause" } }, }, ) # Query the deployment, and verify that the map returned contains the # deployment ID res_json = deploy.get_deployment(deployment_id) assert deployment_id == res_json.get("update_control_map").get( "id"), res_json # Wait for the device to pause in ArtifactInstall deploy.check_expected_statistics(deployment_id, "pause_before_installing", 1) deploy.patch_deployment( deployment_id, update_control_map={ "Priority": 2, "States": { "ArtifactInstall_Enter": { "action": "force_continue" }, "ArtifactReboot_Enter": { "action": "pause" }, }, }, ) # Wait for the device to pause in ArtifactReboot deploy.check_expected_statistics(deployment_id, "pause_before_rebooting", 1) deploy.patch_deployment( deployment_id, update_control_map={ "Priority": 2, "States": { "ArtifactReboot_Enter": { "action": "force_continue" }, "ArtifactCommit_Enter": { "action": "pause" }, }, }, ) # Wait for the device to pause in ArtifactCommit deploy.check_expected_statistics(deployment_id, "pause_before_committing", 1) deploy.patch_deployment( deployment_id, update_control_map={ "Priority": 2, "States": { "ArtifactCommit_Enter": { "action": "force_continue" } }, }, ) deploy.check_expected_status("finished", deployment_id) deploy.check_expected_statistics(deployment_id, "success", 1)