Loading .gitlab-ci.yml +5 −2 Changes for .gitlab-ci.yml: 5 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -68,7 +68,7 @@ ansible-lint: stage: lint extends: .ansible_setup script: - ansible-lint -c .ansible-lint ansible/playbooks ansible/roles ansible/role-template - ansible-lint -c .ansible-lint ansible/playbooks ansible/roles ansible/role-template ansible/tests/test_platform_bootstrap.yml syntax-check: rules: Loading @@ -85,6 +85,8 @@ syntax-check: ansible-playbook -i inventory/r2.example.yml --syntax-check "$playbook" done - ANSIBLE_ROLES_PATH=roles ansible-playbook -i localhost, tests/test_platform_bootstrap.yml python-smoke: rules: - if: '$RUN_SDK_ACCEPTANCE == "1"' Loading @@ -92,7 +94,8 @@ python-smoke: - when: on_success stage: test script: - python3 -m py_compile ansible/roles/oop-platform/files/fm_partners.py ansible/tests/r2_e2e/*.py ci/*.py - python3 -m py_compile ansible/roles/oop-platform/files/fm_partners.py ansible/roles/oop-platform/files/tfsdk_bootstrap.py ansible/tests/r2_e2e/*.py ci/*.py - python3 -m unittest discover -s ansible/tests -p test_tfsdk_bootstrap.py # Pure gate/observation checks; no inventory, cluster access or deployment secrets. sdk-acceptance-checks: Loading README.md +53 −0 Changes for README.md: 53 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -39,3 +39,56 @@ Sergio Giménez <sergio.gimenez@i2cat.net> ## License Apache 2.0. See `LICENSE` and `NOTICE` for attribution requirements. ## Single SRM / TF-SDK bootstrap The existing `oop-platform` role accepts `oop_platform_bootstrap` as one operator declaration. It emits the complete bootstrap and matching read-only credential mounts through the Release 2 chart: ```yaml oop_platform_bootstrap: version: openop.srm.bootstrap/v1 control_paths: - ref: athens adapter_type: kubernetes kubeconfig_secret: name: athens-credentials key: config infrastructure: kube_context: athens namespace: applications - ref: local-workloads adapter_type: kubernetes infrastructure: in_cluster: true namespace: applications zones: [] # Add the real declared topology and bindings. ``` For in-cluster workloads, configure the existing `workloads.namespaces` RBAC setting explicitly. Declaring a control path does not grant permissions. Create the referenced Secrets in the SRM namespace through the existing operator credential process. The role never reads their values or implements a secret resolver. It derives file paths from refs, keeping each control path separate, and strips deployment-only Secret metadata from emitted bootstrap. The SDK identity is derived by SRM from each ref, not repeated in infrastructure. The deployment controller's kubeconfig remains separate from SDK credentials. Remove `controlPaths` from extra chart values. When using `oop_platform_bootstrap`, also remove manually supplied `topology` and `controlPathCredentials`; competing sources fail before deployment. Existing empty defaults preserve health-only deployments. The paired chart provides `/var/run/openop-tfsdk` for private execution files. Use matching SDK 2.0.0rc3, SRM and chart revisions; upgrade or roll back the set together. Bootstrap generation is not a backend-health or credential-validity check. Offline producer tests run in the existing Python CI job. The real-role check also runs locally and in the existing syntax-check job, without cluster access: ```sh python -m unittest discover -s ansible/tests -p test_tfsdk_bootstrap.py ANSIBLE_ROLES_PATH=ansible/roles ansible-playbook -i localhost, ansible/tests/test_platform_bootstrap.yml ``` ansible/inventory/r2.example.yml +7 −11 Changes for ansible/inventory/r2.example.yml: 7 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -71,29 +71,25 @@ all: srmcontroller: workloads: namespaces: [oop-apps] controlPaths: - control_path_ref: k8s-local adapter: kubernetes config: namespace: oop-apps topology: | oop_platform_bootstrap: version: openop.srm.bootstrap/v1 platform_instance_id: {{ oop_platform_federation_id }} platform_instance_id: "{{ oop_platform_federation_id }}" control_paths: - ref: k8s-local adapter_family: compute adapter_type: kubernetes adapter_contract_version: v1 infrastructure: in_cluster: true namespace: oop-apps zones: - ref: {{ oop_platform_federation_id }}-zone name: {{ srm_zone_name }} - ref: "{{ oop_platform_federation_id }}-zone" name: "{{ srm_zone_name }}" kind: resource state: active domains: - ref: {{ oop_platform_federation_id }}-compute name: {{ srm_zone_name }} compute - ref: "{{ oop_platform_federation_id }}-compute" name: "{{ srm_zone_name }} compute" kind: compute state: active capabilities: Loading ansible/playbooks/scenarios/r2_existing_cluster/README.md +21 −32 Changes for ansible/playbooks/scenarios/r2_existing_cluster/README.md: 21 added lines, 32 removed lines. Original line number Diff line number Diff line Loading @@ -210,44 +210,37 @@ declaration Today the only implementation reads a file; a live source could replace it later without changing SRM. The chart's `srm.srmcontroller.topology` and `controlPaths` are empty by default. Helm's kind environment fills them in for you; on any other cluster the role leaves them empty. SRM then logs `bootstrap_topology_not_configured` and has no zones, so OEG lists nothing to deploy to, and any agreement in `federate.yml` fails with `no zone named ... in SRM`. The chart's bootstrap is empty by default. The role accepts one `oop_platform_bootstrap` declaration and generates the complete topology file and any credential mount metadata. With empty defaults, SRM logs `bootstrap_topology_not_configured` and exposes no zones. Give each operator its zone through `oop_platform_extra_values`. The example below declares one zone whose apps SRM deploys with Helm into namespace `oop-apps` of the operator's own cluster; the test environment runs this setup: For a local workload path, declare the connection explicitly and keep the existing namespace/RBAC setting: ```yaml oop_platform_extra_values: srm: srmcontroller: workloads: namespaces: [oop-apps] # created, with a Role for SRM's ServiceAccount controlPaths: - control_path_ref: k8s-local adapter: kubernetes config: namespace: oop-apps topology: | namespaces: [oop-apps] oop_platform_bootstrap: version: openop.srm.bootstrap/v1 platform_instance_id: {{ oop_platform_federation_id }} platform_instance_id: "{{ oop_platform_federation_id }}" control_paths: - ref: k8s-local adapter_family: compute adapter_type: kubernetes adapter_contract_version: v1 infrastructure: in_cluster: true namespace: oop-apps zones: - ref: {{ oop_platform_federation_id }}-zone name: {{ srm_zone_name }} - ref: "{{ oop_platform_federation_id }}-zone" name: "{{ srm_zone_name }}" kind: resource state: active domains: - ref: {{ oop_platform_federation_id }}-compute name: {{ srm_zone_name }} compute - ref: "{{ oop_platform_federation_id }}-compute" name: "{{ srm_zone_name }} compute" kind: compute state: active capabilities: Loading @@ -259,17 +252,13 @@ oop_platform_extra_values: - {ref: deploy-workload-via-k8s-local, control_path_ref: k8s-local, is_default: true, state: active} ``` `srm_zone_name` is a host variable (`Barcelona`, `Paris`, ...): the name users see, and the name agreements refer to. The zone declares one capability, `workload`, because that's all TF-SDK's `kubernetes` adapter serves: it installs, updates, removes and reads Helm releases and containers. It can't report free resources, so a `query_available_resources` capability bound to it gets no actions, and placement never uses it; SRM keeps no capacity of its own either ([ADR-0002](https://labs.etsi.org/rep/oop/architecture/-/blob/develop/decisions/0002-no-stored-capacity.md)). The adapter only reads `namespace` from its config and runs `helm` as SRM's own ServiceAccount, so it deploys into the cluster SRM runs in, in the namespaces listed under `workloads.namespaces`. `srm_zone_name` is the host variable used in public zone names and agreements. The Kubernetes adapter serves workload lifecycle operations; it does not report free capacity. SRM retains topology/placement responsibility. For remote clusters, see the repository README's `kubeconfig_secret` declaration. Remove legacy `controlPaths` and manually duplicated topology/mount values when using the generated declaration. Configure workload RBAC separately; declaring a control path does not grant permissions. ## Step 2: federate the operators Loading ansible/roles/oop-platform/defaults/main.yml +3 −0 Changes for ansible/roles/oop-platform/defaults/main.yml: 3 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -88,6 +88,9 @@ oop_platform_db_passwords: {} oop_platform_keycloak_admin_password: "" oop_platform_groq_api_key: "" # One operator declaration; the role generates bootstrap YAML and credential mounts. oop_platform_bootstrap: {} # Merged over everything above, for chart settings this role does not expose. oop_platform_extra_values: {} Loading Loading
.gitlab-ci.yml +5 −2 Changes for .gitlab-ci.yml: 5 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -68,7 +68,7 @@ ansible-lint: stage: lint extends: .ansible_setup script: - ansible-lint -c .ansible-lint ansible/playbooks ansible/roles ansible/role-template - ansible-lint -c .ansible-lint ansible/playbooks ansible/roles ansible/role-template ansible/tests/test_platform_bootstrap.yml syntax-check: rules: Loading @@ -85,6 +85,8 @@ syntax-check: ansible-playbook -i inventory/r2.example.yml --syntax-check "$playbook" done - ANSIBLE_ROLES_PATH=roles ansible-playbook -i localhost, tests/test_platform_bootstrap.yml python-smoke: rules: - if: '$RUN_SDK_ACCEPTANCE == "1"' Loading @@ -92,7 +94,8 @@ python-smoke: - when: on_success stage: test script: - python3 -m py_compile ansible/roles/oop-platform/files/fm_partners.py ansible/tests/r2_e2e/*.py ci/*.py - python3 -m py_compile ansible/roles/oop-platform/files/fm_partners.py ansible/roles/oop-platform/files/tfsdk_bootstrap.py ansible/tests/r2_e2e/*.py ci/*.py - python3 -m unittest discover -s ansible/tests -p test_tfsdk_bootstrap.py # Pure gate/observation checks; no inventory, cluster access or deployment secrets. sdk-acceptance-checks: Loading
README.md +53 −0 Changes for README.md: 53 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -39,3 +39,56 @@ Sergio Giménez <sergio.gimenez@i2cat.net> ## License Apache 2.0. See `LICENSE` and `NOTICE` for attribution requirements. ## Single SRM / TF-SDK bootstrap The existing `oop-platform` role accepts `oop_platform_bootstrap` as one operator declaration. It emits the complete bootstrap and matching read-only credential mounts through the Release 2 chart: ```yaml oop_platform_bootstrap: version: openop.srm.bootstrap/v1 control_paths: - ref: athens adapter_type: kubernetes kubeconfig_secret: name: athens-credentials key: config infrastructure: kube_context: athens namespace: applications - ref: local-workloads adapter_type: kubernetes infrastructure: in_cluster: true namespace: applications zones: [] # Add the real declared topology and bindings. ``` For in-cluster workloads, configure the existing `workloads.namespaces` RBAC setting explicitly. Declaring a control path does not grant permissions. Create the referenced Secrets in the SRM namespace through the existing operator credential process. The role never reads their values or implements a secret resolver. It derives file paths from refs, keeping each control path separate, and strips deployment-only Secret metadata from emitted bootstrap. The SDK identity is derived by SRM from each ref, not repeated in infrastructure. The deployment controller's kubeconfig remains separate from SDK credentials. Remove `controlPaths` from extra chart values. When using `oop_platform_bootstrap`, also remove manually supplied `topology` and `controlPathCredentials`; competing sources fail before deployment. Existing empty defaults preserve health-only deployments. The paired chart provides `/var/run/openop-tfsdk` for private execution files. Use matching SDK 2.0.0rc3, SRM and chart revisions; upgrade or roll back the set together. Bootstrap generation is not a backend-health or credential-validity check. Offline producer tests run in the existing Python CI job. The real-role check also runs locally and in the existing syntax-check job, without cluster access: ```sh python -m unittest discover -s ansible/tests -p test_tfsdk_bootstrap.py ANSIBLE_ROLES_PATH=ansible/roles ansible-playbook -i localhost, ansible/tests/test_platform_bootstrap.yml ```
ansible/inventory/r2.example.yml +7 −11 Changes for ansible/inventory/r2.example.yml: 7 added lines, 11 removed lines. Original line number Diff line number Diff line Loading @@ -71,29 +71,25 @@ all: srmcontroller: workloads: namespaces: [oop-apps] controlPaths: - control_path_ref: k8s-local adapter: kubernetes config: namespace: oop-apps topology: | oop_platform_bootstrap: version: openop.srm.bootstrap/v1 platform_instance_id: {{ oop_platform_federation_id }} platform_instance_id: "{{ oop_platform_federation_id }}" control_paths: - ref: k8s-local adapter_family: compute adapter_type: kubernetes adapter_contract_version: v1 infrastructure: in_cluster: true namespace: oop-apps zones: - ref: {{ oop_platform_federation_id }}-zone name: {{ srm_zone_name }} - ref: "{{ oop_platform_federation_id }}-zone" name: "{{ srm_zone_name }}" kind: resource state: active domains: - ref: {{ oop_platform_federation_id }}-compute name: {{ srm_zone_name }} compute - ref: "{{ oop_platform_federation_id }}-compute" name: "{{ srm_zone_name }} compute" kind: compute state: active capabilities: Loading
ansible/playbooks/scenarios/r2_existing_cluster/README.md +21 −32 Changes for ansible/playbooks/scenarios/r2_existing_cluster/README.md: 21 added lines, 32 removed lines. Original line number Diff line number Diff line Loading @@ -210,44 +210,37 @@ declaration Today the only implementation reads a file; a live source could replace it later without changing SRM. The chart's `srm.srmcontroller.topology` and `controlPaths` are empty by default. Helm's kind environment fills them in for you; on any other cluster the role leaves them empty. SRM then logs `bootstrap_topology_not_configured` and has no zones, so OEG lists nothing to deploy to, and any agreement in `federate.yml` fails with `no zone named ... in SRM`. The chart's bootstrap is empty by default. The role accepts one `oop_platform_bootstrap` declaration and generates the complete topology file and any credential mount metadata. With empty defaults, SRM logs `bootstrap_topology_not_configured` and exposes no zones. Give each operator its zone through `oop_platform_extra_values`. The example below declares one zone whose apps SRM deploys with Helm into namespace `oop-apps` of the operator's own cluster; the test environment runs this setup: For a local workload path, declare the connection explicitly and keep the existing namespace/RBAC setting: ```yaml oop_platform_extra_values: srm: srmcontroller: workloads: namespaces: [oop-apps] # created, with a Role for SRM's ServiceAccount controlPaths: - control_path_ref: k8s-local adapter: kubernetes config: namespace: oop-apps topology: | namespaces: [oop-apps] oop_platform_bootstrap: version: openop.srm.bootstrap/v1 platform_instance_id: {{ oop_platform_federation_id }} platform_instance_id: "{{ oop_platform_federation_id }}" control_paths: - ref: k8s-local adapter_family: compute adapter_type: kubernetes adapter_contract_version: v1 infrastructure: in_cluster: true namespace: oop-apps zones: - ref: {{ oop_platform_federation_id }}-zone name: {{ srm_zone_name }} - ref: "{{ oop_platform_federation_id }}-zone" name: "{{ srm_zone_name }}" kind: resource state: active domains: - ref: {{ oop_platform_federation_id }}-compute name: {{ srm_zone_name }} compute - ref: "{{ oop_platform_federation_id }}-compute" name: "{{ srm_zone_name }} compute" kind: compute state: active capabilities: Loading @@ -259,17 +252,13 @@ oop_platform_extra_values: - {ref: deploy-workload-via-k8s-local, control_path_ref: k8s-local, is_default: true, state: active} ``` `srm_zone_name` is a host variable (`Barcelona`, `Paris`, ...): the name users see, and the name agreements refer to. The zone declares one capability, `workload`, because that's all TF-SDK's `kubernetes` adapter serves: it installs, updates, removes and reads Helm releases and containers. It can't report free resources, so a `query_available_resources` capability bound to it gets no actions, and placement never uses it; SRM keeps no capacity of its own either ([ADR-0002](https://labs.etsi.org/rep/oop/architecture/-/blob/develop/decisions/0002-no-stored-capacity.md)). The adapter only reads `namespace` from its config and runs `helm` as SRM's own ServiceAccount, so it deploys into the cluster SRM runs in, in the namespaces listed under `workloads.namespaces`. `srm_zone_name` is the host variable used in public zone names and agreements. The Kubernetes adapter serves workload lifecycle operations; it does not report free capacity. SRM retains topology/placement responsibility. For remote clusters, see the repository README's `kubeconfig_secret` declaration. Remove legacy `controlPaths` and manually duplicated topology/mount values when using the generated declaration. Configure workload RBAC separately; declaring a control path does not grant permissions. ## Step 2: federate the operators Loading
ansible/roles/oop-platform/defaults/main.yml +3 −0 Changes for ansible/roles/oop-platform/defaults/main.yml: 3 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -88,6 +88,9 @@ oop_platform_db_passwords: {} oop_platform_keycloak_admin_password: "" oop_platform_groq_api_key: "" # One operator declaration; the role generates bootstrap YAML and credential mounts. oop_platform_bootstrap: {} # Merged over everything above, for chart settings this role does not expose. oop_platform_extra_values: {} Loading