diff --git a/reconcile/cli.py b/reconcile/cli.py index 76f968695d..f6a19baed5 100644 --- a/reconcile/cli.py +++ b/reconcile/cli.py @@ -3356,12 +3356,6 @@ def status_page_maintenances(ctx): required=False, envvar="OCM_ENV", ) -@click.option( - "--ocm-org-ids", - help="A comma seperated list of OCM organization IDs the integration should operator on. If none is specified, all organizations are considered.", - required=False, - envvar="OCM_ORG_IDS", -) @click.option( "--group-provider", help="A group provider spec is the form of ::.", @@ -3369,16 +3363,14 @@ def status_page_maintenances(ctx): multiple=True, ) @click.pass_context -def ocm_standalone_user_management(ctx, ocm_env, ocm_org_ids, group_provider): +def ocm_standalone_user_management(ctx, ocm_env, group_provider): from reconcile.oum.base import OCMUserManagementIntegrationParams from reconcile.oum.standalone import OCMStandaloneUserManagementIntegration - ocm_organization_ids = set(ocm_org_ids.split(",")) if ocm_org_ids else None run_class_integration( OCMStandaloneUserManagementIntegration( OCMUserManagementIntegrationParams( ocm_environment=ocm_env, - ocm_organization_ids=ocm_organization_ids, group_provider_specs=group_provider, ), ), diff --git a/reconcile/gql_definitions/oum/__init__.py b/reconcile/gql_definitions/oum/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/reconcile/gql_definitions/oum/organizations.gql b/reconcile/gql_definitions/oum/organizations.gql new file mode 100644 index 0000000000..bb9603b179 --- /dev/null +++ b/reconcile/gql_definitions/oum/organizations.gql @@ -0,0 +1,14 @@ +# qenerate: plugin=pydantic_v1 + +query OUMOrganizations { + organizations: ocm_instances_v1 { + name + environment { + ...OCMEnvironment + } + orgId + disable { + ...DisableAutomations + } + } +} diff --git a/reconcile/gql_definitions/oum/organizations.py b/reconcile/gql_definitions/oum/organizations.py new file mode 100644 index 0000000000..e92d9873e9 --- /dev/null +++ b/reconcile/gql_definitions/oum/organizations.py @@ -0,0 +1,96 @@ +""" +Generated by qenerate plugin=pydantic_v1. DO NOT MODIFY MANUALLY! +""" +from collections.abc import Callable # noqa: F401 # pylint: disable=W0611 +from datetime import datetime # noqa: F401 # pylint: disable=W0611 +from enum import Enum # noqa: F401 # pylint: disable=W0611 +from typing import ( # noqa: F401 # pylint: disable=W0611 + Any, + Optional, + Union, +) + +from pydantic import ( # noqa: F401 # pylint: disable=W0611 + BaseModel, + Extra, + Field, + Json, +) + +from reconcile.gql_definitions.fragments.disable import DisableAutomations +from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment + + +DEFINITION = """ +fragment DisableAutomations on DisableClusterAutomations_v1 { + integrations +} + +fragment OCMEnvironment on OpenShiftClusterManagerEnvironment_v1 { + name + description + labels + url + accessTokenClientId + accessTokenUrl + accessTokenClientSecret { + ... VaultSecret + } +} + +fragment VaultSecret on VaultSecret_v1 { + path + field + version + format +} + +query OUMOrganizations { + organizations: ocm_instances_v1 { + name + environment { + ...OCMEnvironment + } + orgId + disable { + ...DisableAutomations + } + } +} +""" + + +class ConfiguredBaseModel(BaseModel): + class Config: + smart_union=True + extra=Extra.forbid + + +class OpenShiftClusterManagerV1(ConfiguredBaseModel): + name: str = Field(..., alias="name") + environment: OCMEnvironment = Field(..., alias="environment") + org_id: str = Field(..., alias="orgId") + disable: Optional[DisableAutomations] = Field(..., alias="disable") + + +class OUMOrganizationsQueryData(ConfiguredBaseModel): + organizations: Optional[list[OpenShiftClusterManagerV1]] = Field(..., alias="organizations") + + +def query(query_func: Callable, **kwargs: Any) -> OUMOrganizationsQueryData: + """ + This is a convenience function which queries and parses the data into + concrete types. It should be compatible with most GQL clients. + You do not have to use it to consume the generated data classes. + Alternatively, you can also mime and alternate the behavior + of this function in the caller. + + Parameters: + query_func (Callable): Function which queries your GQL Server + kwargs: optional arguments that will be passed to the query function + + Returns: + OUMOrganizationsQueryData: queried data parsed into generated classes + """ + raw_data: dict[Any, Any] = query_func(DEFINITION, **kwargs) + return OUMOrganizationsQueryData(**raw_data) diff --git a/reconcile/oum/base.py b/reconcile/oum/base.py index eb36492abf..896ea7753f 100644 --- a/reconcile/oum/base.py +++ b/reconcile/oum/base.py @@ -9,6 +9,12 @@ query as ocm_environment_query, ) from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment +from reconcile.gql_definitions.oum.organizations import ( + OpenShiftClusterManagerV1, +) +from reconcile.gql_definitions.oum.organizations import ( + query as ocm_orgs_query, +) from reconcile.oum.metrics import ( OCMUserManagementOrganizationActionCounter as ReconcileActionCounter, ) @@ -35,6 +41,7 @@ gql, metrics, ) +from reconcile.utils.disabled_integrations import integration_is_enabled from reconcile.utils.ocm.base import ( CAPABILITY_MANAGE_CLUSTER_ADMIN, OCMClusterGroupId, @@ -56,7 +63,6 @@ class OCMUserManagementIntegrationParams(PydanticRunParams): ocm_environment: str | None = None - ocm_organization_ids: set[str] | None = None group_provider_specs: list[str] @@ -87,7 +93,7 @@ def get_ocm_environments(self) -> list[OCMEnvironment]: @abstractmethod def get_user_mgmt_config_for_ocm_env( - self, ocm_env: OCMEnvironment, org_ids: set[str] | None + self, ocm_env: OCMEnvironment ) -> dict[str, OrganizationUserManagementConfiguration]: """ Discover cluster user mgmt configurations in the given OCM environment. @@ -101,9 +107,7 @@ def reconcile_ocm_environment(self, dry_run: bool, ocm_env: OCMEnvironment) -> N Processes user management configuration for all OCM organizations within the given OCM environment. """ - org_configs = self.get_user_mgmt_config_for_ocm_env( - ocm_env, self.params.ocm_organization_ids - ) + org_configs = self.get_user_mgmt_config_for_ocm_env(ocm_env) ocm_api = init_ocm_base_client(ocm_env, self.secret_reader) for org_id, org_config in org_configs.items(): @@ -385,3 +389,14 @@ def get_group_providers( else: raise ValueError(f"unknown group member provider type {provider_type}") return providers + + +def get_ocm_orgs_from_env( + env_name: str, int_name: str +) -> list[OpenShiftClusterManagerV1]: + orgs = ocm_orgs_query(gql.get_api().query).organizations + return [ + org + for org in orgs or [] + if integration_is_enabled(int_name, org) and org.environment.name == env_name + ] diff --git a/reconcile/oum/standalone.py b/reconcile/oum/standalone.py index b6d2b87822..5f27a577d3 100644 --- a/reconcile/oum/standalone.py +++ b/reconcile/oum/standalone.py @@ -3,7 +3,7 @@ from datetime import timedelta from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment -from reconcile.oum.base import OCMUserManagementIntegration +from reconcile.oum.base import OCMUserManagementIntegration, get_ocm_orgs_from_env from reconcile.oum.labelset import build_cluster_config_from_labels from reconcile.oum.models import ( ClusterError, @@ -35,12 +35,14 @@ def name(self) -> str: return "ocm-standalone-user-management" def get_user_mgmt_config_for_ocm_env( - self, ocm_env: OCMEnvironment, org_ids: set[str] | None + self, ocm_env: OCMEnvironment ) -> dict[str, OrganizationUserManagementConfiguration]: ocm_api = init_ocm_base_client(ocm_env, self.secret_reader) clusters_by_org = discover_clusters( ocm_api=ocm_api, - org_ids=org_ids, + org_ids={ + org.org_id for org in get_ocm_orgs_from_env(ocm_env.name, self.name) + }, ) configs: dict[str, OrganizationUserManagementConfiguration] = {} for org_id, org_clusters in clusters_by_org.items(): diff --git a/reconcile/test/ocm/oum/test_oum_base.py b/reconcile/test/ocm/oum/test_oum_base.py index 9478e2d1ed..a699cb751b 100644 --- a/reconcile/test/ocm/oum/test_oum_base.py +++ b/reconcile/test/ocm/oum/test_oum_base.py @@ -396,7 +396,7 @@ def test_build_spec_from_config_cluster_admin_with_capability( class MockOCMUserManagementIntegration(OCMUserManagementIntegration): def get_user_mgmt_config_for_ocm_env( - self, ocm_env: OCMEnvironment, org_ids: set[str] | None + self, ocm_env: OCMEnvironment ) -> dict[str, OrganizationUserManagementConfiguration]: return {}