async def test_conflict_raises(faker, namespace, api_client): core = CoreV1Api(api_client) name = faker.domain_word() ns = namespace.metadata.name password1 = faker.password(length=12) password2 = faker.password(length=12) await core.create_namespaced_secret( namespace=ns, body=V1Secret( data={"password": b64encode(password1)}, metadata=V1ObjectMeta(name=name), type="Opaque", ), ) with pytest.raises(ApiException): await call_kubeapi( core.create_namespaced_secret, logger, namespace=ns, body=V1Secret( data={"password": b64encode(password2)}, metadata=V1ObjectMeta(name=name), type="Opaque", ), ) secret = await core.read_namespaced_secret(name=name, namespace=ns) assert b64decode(secret.data["password"]) == password1
async def test_conflict_logs(faker, namespace, caplog, api_client): caplog.set_level(logging.DEBUG, logger=__name__) core = CoreV1Api(api_client) name = faker.domain_word() ns = namespace.metadata.name password1 = faker.password(length=12) password2 = faker.password(length=12) await core.create_namespaced_secret( namespace=ns, body=V1Secret( data={"password": b64encode(password1)}, metadata=V1ObjectMeta(name=name), type="Opaque", ), ) await call_kubeapi( core.create_namespaced_secret, logger, continue_on_conflict=True, namespace=ns, body=V1Secret( data={"password": b64encode(password2)}, metadata=V1ObjectMeta(name=name), type="Opaque", ), ) secret = await core.read_namespaced_secret(name=name, namespace=ns) assert b64decode(secret.data["password"]) == password1 assert ( f"Failed creating V1Secret '{ns}/{name}' because it already exists. Continuing." in caplog.messages )
def get_system_user_secret(owner_references: Optional[List[V1OwnerReference]], name: str, labels: LabelType) -> V1Secret: return V1Secret( data={"password": b64encode(gen_password(50))}, metadata=V1ObjectMeta( name=f"user-system-{name}", labels=labels, owner_references=owner_references, ), type="Opaque", )
async def test_success(faker, namespace, api_client): core = CoreV1Api(api_client) name = faker.domain_word() password = faker.password(length=12) await call_kubeapi( core.create_namespaced_secret, logger, namespace=namespace.metadata.name, body=V1Secret( data={"password": b64encode(password)}, metadata=V1ObjectMeta(name=name), type="Opaque", ), ) secret = await core.read_namespaced_secret( name=name, namespace=namespace.metadata.name ) assert b64decode(secret.data["password"]) == password
async def test_update_cluster_password(faker, namespace, cleanup_handler, kopf_runner, api_client): coapi = CustomObjectsApi(api_client) core = CoreV1Api(api_client) name = faker.domain_word() password = faker.password(length=40) new_password = faker.password(length=40) username = faker.user_name() cleanup_handler.append( core.delete_persistent_volume( name=f"temp-pv-{namespace.metadata.name}-{name}")) await asyncio.gather( core.create_namespaced_secret( namespace=namespace.metadata.name, body=V1Secret( data={"password": b64encode(password)}, metadata=V1ObjectMeta(name=f"user-{name}", labels={LABEL_USER_PASSWORD: "******"}), type="Opaque", ), ), ) await coapi.create_namespaced_custom_object( group=API_GROUP, version="v1", plural=RESOURCE_CRATEDB, namespace=namespace.metadata.name, body={ "apiVersion": "cloud.crate.io/v1", "kind": "CrateDB", "metadata": { "name": name }, "spec": { "cluster": { "imageRegistry": "crate", "name": "my-crate-cluster", "version": CRATE_VERSION, }, "nodes": { "data": [{ "name": "data", "replicas": 1, "resources": { "cpus": 0.5, "memory": "1Gi", "heapRatio": 0.25, "disk": { "storageClass": "default", "size": "16GiB", "count": 1, }, }, }] }, "users": [ { "name": username, "password": { "secretKeyRef": { "key": "password", "name": f"user-{name}", } }, }, ], }, }, ) host = await asyncio.wait_for( get_public_host(core, namespace.metadata.name, name), # It takes a while to retrieve an external IP on AKS. timeout=DEFAULT_TIMEOUT * 5, ) await core.patch_namespaced_secret( namespace=namespace.metadata.name, name=f"user-{name}", body=V1Secret(data={"password": b64encode(new_password)}, ), ) await assert_wait_for( True, is_password_set, host, new_password, username, timeout=DEFAULT_TIMEOUT * 5, )
async def test_bootstrap_license( bootstrap_system_user: mock.AsyncMock, bootstrap_license_mock: mock.AsyncMock, faker, namespace, cleanup_handler, kopf_runner, api_client, ): coapi = CustomObjectsApi(api_client) core = CoreV1Api(api_client) name = faker.domain_word() license = base64.b64encode(faker.binary(64)).decode() cleanup_handler.append( core.delete_persistent_volume( name=f"temp-pv-{namespace.metadata.name}-{name}"), ) await core.create_namespaced_secret( namespace=namespace.metadata.name, body=V1Secret( data={"license": b64encode(license)}, metadata=V1ObjectMeta(name=f"license-{name}"), type="Opaque", ), ) await coapi.create_namespaced_custom_object( group=API_GROUP, version="v1", plural=RESOURCE_CRATEDB, namespace=namespace.metadata.name, body={ "apiVersion": "cloud.crate.io/v1", "kind": "CrateDB", "metadata": { "name": name }, "spec": { "cluster": { "imageRegistry": "crate", "license": { "secretKeyRef": { "key": "license", "name": f"license-{name}" }, }, "name": "my-crate-cluster", "version": CRATE_VERSION, }, "nodes": { "data": [{ "name": "data", "replicas": 1, "resources": { "cpus": 0.5, "memory": "1Gi", "heapRatio": 0.25, "disk": { "storageClass": "default", "size": "16GiB", "count": 1, }, }, }] }, }, }, ) await assert_wait_for( True, was_license_set, bootstrap_license_mock, mock.ANY, namespace.metadata.name, f"crate-data-data-{name}-0", False, {"secretKeyRef": { "key": "license", "name": f"license-{name}" }}, timeout=DEFAULT_TIMEOUT * 3, )
async def test_bootstrap_users( bootstrap_license_mock: mock.AsyncMock, faker, namespace, cleanup_handler, kopf_runner, ): coapi = CustomObjectsApi() core = CoreV1Api() name = faker.domain_word() password1 = faker.password(length=40) password2 = faker.password(length=30) username1 = faker.user_name() username2 = faker.user_name() cleanup_handler.append( core.delete_persistent_volume(name=f"temp-pv-{namespace.metadata.name}-{name}") ) await asyncio.gather( core.create_namespaced_secret( namespace=namespace.metadata.name, body=V1Secret( data={"password": b64encode(password1)}, metadata=V1ObjectMeta(name=f"user-{name}-1"), type="Opaque", ), ), core.create_namespaced_secret( namespace=namespace.metadata.name, body=V1Secret( data={"password": b64encode(password2)}, metadata=V1ObjectMeta(name=f"user-{name}-2"), type="Opaque", ), ), ) await coapi.create_namespaced_custom_object( group=API_GROUP, version="v1", plural=RESOURCE_CRATEDB, namespace=namespace.metadata.name, body={ "apiVersion": "cloud.crate.io/v1", "kind": "CrateDB", "metadata": {"name": name}, "spec": { "cluster": { "imageRegistry": "crate", "name": "my-crate-cluster", "version": "4.1.5", }, "nodes": { "data": [ { "name": "data", "replicas": 1, "resources": { "cpus": 0.5, "memory": "1Gi", "heapRatio": 0.25, "disk": { "storageClass": "default", "size": "16GiB", "count": 1, }, }, } ] }, "users": [ { "name": username1, "password": { "secretKeyRef": { "key": "password", "name": f"user-{name}-1", } }, }, { "name": username2, "password": { "secretKeyRef": { "key": "password", "name": f"user-{name}-2", } }, }, ], }, }, ) host = await asyncio.wait_for( get_public_host(core, namespace.metadata.name, name), timeout=BACKOFF_TIME * 5, # It takes a while to retrieve an external IP on AKS. ) password_system = await get_system_user_password( namespace.metadata.name, name, core ) await assert_wait_for( True, does_user_exist, host, password_system, SYSTEM_USERNAME, timeout=BACKOFF_TIME * 5, ) await assert_wait_for( True, does_user_exist, host, password1, username1, timeout=BACKOFF_TIME * 3, ) await assert_wait_for( True, does_user_exist, host, password2, username2, timeout=BACKOFF_TIME * 3, )
async def test_resume_set_secret_labels( faker, namespace, cleanup_handler, kopf_runner, api_client, ): core = CoreV1Api(api_client) name = faker.domain_word() password1 = faker.password(length=40) password2 = faker.password(length=40) cleanup_handler.append( core.delete_persistent_volume( name=f"temp-pv-{namespace.metadata.name}-{name}")) await asyncio.gather( core.create_namespaced_secret( namespace=namespace.metadata.name, body=V1Secret( data={"password": b64encode(password1)}, metadata=V1ObjectMeta(name=f"user-{name}-1"), type="Opaque", ), ), core.create_namespaced_secret( namespace=namespace.metadata.name, body=V1Secret( data={"password": b64encode(password2)}, metadata=V1ObjectMeta(name=f"user-{name}-2", labels={LABEL_USER_PASSWORD: "******"}), type="Opaque", ), ), ) secret_1 = await core.read_namespaced_secret( name=f"user-{name}-1", namespace=namespace.metadata.name) secret_2 = await core.read_namespaced_secret( name=f"user-{name}-2", namespace=namespace.metadata.name) assert secret_1.metadata.labels is None assert LABEL_USER_PASSWORD in secret_2.metadata.labels await update_cratedb_resource( namespace=namespace.metadata.name, name=f"user-{name}", spec={ "cluster": { "imageRegistry": "crate", "name": "my-crate-cluster", "version": CRATE_VERSION, }, "nodes": { "data": [{ "name": "data", "replicas": 1, "resources": { "cpus": 0.5, "disk": { "count": 1, "size": "16GiB", "storageClass": "default", }, "heapRatio": 0.25, "memory": "1Gi", }, }] }, "users": [ { "name": name, "password": { "secretKeyRef": { "key": b64encode(password1), "name": f"user-{name}-1", } }, }, { "name": name, "password": { "secretKeyRef": { "key": b64encode(password1), "name": f"user-{name}-2", } }, }, ], }, ) secret_1_after_resume = await core.read_namespaced_secret( name=f"user-{name}-1", namespace=namespace.metadata.name) secret_2_after_resume = await core.read_namespaced_secret( name=f"user-{name}-2", namespace=namespace.metadata.name) assert LABEL_USER_PASSWORD in secret_1_after_resume.metadata.labels assert LABEL_USER_PASSWORD in secret_2_after_resume.metadata.labels