Decoupling ACM-R from Policy Framework
- 1 Background
- 1.1 Analysis of Dependencies & Proposed Changes
- 1.2 Release Plan
- 1.2.1 Release 1 - POM decoupling
- 1.2.1.1 Parent POM cleanup
- 1.2.1.2 Future Dependency Uplifts
- 1.2.2 Release 2 - Spring Boot 4
- 1.2.3 Release 3 - Spring Kafka: ACM-R only
- 1.2.4 Release 4 - De-duplicating Spring & Logback configs
- 1.2.5 Release 5 - Spring Kafka: participant intermediary
- 1.2.6 Additional items that can be delivered in any release
- 1.2.6.1 Java Bean Validation
- 1.2.1 Release 1 - POM decoupling
Background
Currently, developing, building & releasing ACM as a standalone component directly requires maintenance & delivery of five Policy repos:
policy/parent - integration POM used by all components including ACM
policy/common - kafka client code & utilities used in ACM
policy/models - Tosca model
policy/clamp - ACM source code and docker images
policy/docker - docker-compose, helm charts & CSITs
Indirectly e.g. through CSITs, the remaining 8 policy repos are depended on, e.g. api, pap, pdps.
This can cause delays in the development & delivery of ACM. For example, if a dependency uplift is needed for ACM, currently it is uplifted in the parent POM. An uplift could break another component like Apex PDP, which would lead to test failures in the CSITs for ACM. Additionally, CSITs for ACM are hosted in the docker repo, meaning CSITs do not run on every code commit - only for changes made in the docker repo. This has led to delays caused by late discovery of test failures.
In addition, many unneeded dependencies are included. Inspecting maven dependency tree for ACM Runtime shows dependencies on jetty, jersey & jaxb introduced from policy-common-endpoints, while ACM-R uses Spring Boot with Tomcat as the HTTP server.
In order to minimize delays in development of ACM, it is proposed to decouple ACM from the rest of the Policy Framework, allowing end-to-end development, testing, and delivery using only a single repo (policy/clamp).
The decoupling will enable further improvements, such as dependency auto-uplift, which is currently not feasible in multi-repo setup.
Analysis of Dependencies & Proposed Changes
The following table shows each Policy Framework dependency used by ACM (clamp repo), what they currently used for, proposed changes, and risk of breakage. Note the changes are largely independent and can be worked on in parallel, and in any order.
Purpose | Repo | Dependency Packages | Proposed Change | Cost | Time | Risk | Jira | |
|---|---|---|---|---|---|---|---|---|
| 1 | Dependency Management | parent | org.onap.policy.parent.integration:pom | Integrate dependencies to clamp pom, may also need plugin configs, checkstyle, jacoco, etc. | M | 1 Week | Medium | |
| 2 | Exception Class Definitions | models | org.onap.policy.models.errors.concepts.* | Copy the classes to clamp. | XS | Hours | None | |
| 3 | Exception Base | models | org.onap.policy.models.base.PfModelException | Copy to clamp preserving package structure. | XS | Hours | High* | |
| 4 | TOSCA Support | models | org.onap.policy.models.tosca.* | Copy to clamp preserving package structure. | S | 1 Day | High * | |
| 5 | Policy Participant (PDP Dependency) | models | org.onap.policy.models.pdp.concepts.* | Classes are simple DTOs, can be copied. | XS | Hours | None | |
| 6 | JPA Model | models | org.onap.policy.models.base.PfAuthorative | Note: Overlaps with Bean Validation. Recommend copying some classes like PfAuthoratative to clamp, while replacing some usages with Bean Validation. | M | 1 Week | Medium | |
| 7 | YAML Support | common | org.onap.policy.common.spring.utils.YamlHttpMessageConverter | Copy the class to clamp. | XS | Hours | None | |
| 8 | TOSCA Template (Examples Module) | common | org.onap.policy.common.gson.InstantAsMillisTypeAdapter | Copy the class to clamp. | XS | Hours | None | |
| 9 | Test Utility: toString tester | common | org.onap.policy.common.utils.test.ToStringTester | Copy the class to clamp. | XS | Hours | None | |
| 10 | Test Utility: Resource Loading | common | org.onap.policy.common.utils.resources.ResourceUtils | Copy the class to clamp. Alternately replace with Spring Boot resource loader | XS | Hours | None | |
| 11 | Hibernate Naming Strategy | common | org.onap.policy.common.spring.utils.CustomImplicitNamingStrategy | Copy the class to clamp. Note it is set in application.yaml and AcRuntimeParameters.yaml; double-check if the custom class is needed, if so remove from each AcRuntimeParameters.yaml. | S | 2 Days | Low | |
| 12 | Test Utility: Mock Server | common | org.onap.policy.common.endpoints.http.server.* | Replace with off-the-shelf component e.g. OkHttp MockWebServer. | M | 1 Week | None | |
| 13 | Policy Participant (REST Communication) | common | org.onap.policy.common.endpoints.http.client.* | Replace with Spring’s RestTemplate/WebClient/RestClient. | M | 1 Week | None | |
| 14 | JSON/YAML & other Type Conversions | common | org.onap.policy.common.utils.coder.* | Copy the classes to clamp? Alternatively, replacing Gson with Jackson can be done to remove further dependencies. | M | 1 Week | None | |
| 15 | Java Bean Validation | common | org.onap.policy.common.parameters.annotations.* | Replace with spring-boot-starter-validation (JSR-380). | M | 1 Week | Medium | |
| 16 | Kafka Messaging | common | org.onap.policy.common.endpoints.listeners.* | Replace with Spring Kafka. | L | 3 Weeks | High | |
| 17 | Spring Config | docker | policy/docker repo overrides with AcRuntimeParameters.yaml | Have only one application.yaml in clamp, override settings with env vars | L | 3 Weeks | High | |
| 18 | Logback Config | docker | policy/docker repo overrides logback.xml | Have only one logback.xml in clamp, remove overrides | M | 1 Week | Medium | |
| 19 | CSITs | docker | policy/docker repo contains clamp CSITs | Move to clamp repo and make CSITs run per commit | M | 1 Week | Low |
* risk can be eliminated by preserving original package structure.
The epic is estimated to be 3.5 person-months of development effort.
Release Plan
Duration: 5 releases, spanning less than 4 to 5 months
To minimize risk of breaking changes, it is proposed that high risk items be spread across multiple releases. This will help with traceability in the event of a bug.
Item | Risk Level | Reward Level | |
|---|---|---|---|
| 1 | POM decoupling | Medium | High |
| 2 | Spring Boot 4 | High | Medium |
| 3 | Spring Kafka: ACM-R only | Medium | High |
| 4 | De-duplicating Spring & Logback configs | Medium | High |
| 5 | Spring Kafka: participant intermediary | High | High |
Note: the above release plan does not explicitly include low-risk items, which could be done in any release, e.g. test utilities, policy participant changes.
Release 1 - POM decoupling
Risk: None if done correctly; this is mainly copying files, but care must be taken not to change package structures for packages exposed by intermediary.
Mitigation: Require all changes to not modify participant-impl source code; can be observed in code review.
Copy all used Policy Framework dependencies directly into clamp repo, without modification, i.e. maintaining existing package structures, and remove POM dependencies. This virtually eliminates all risk, since no actual modifications are made.
copy used classes/packages from policy-models into clamp/models maintaining original package structure
copy used classes/packages from policy-common into clamp/common maintaining original package structure
copy policy-parent/integration into clamp/parent without modification
fix POM dependencies to use clamp versions, e.g. org.onap.policy.models:policy-models-tosca becomes org.onap.policy.clamp:models
verify using
mvn dependency:treeand running CSITs
This means that any future POM changes can be done in clamp repo only, not affecting any other PF component. Everything is under a single repo, other than clamp CSITs, which is in docker repo.
Parent POM cleanup
By copying the entire parent POM without modification, we will be copying things we don't need (e.g. clamp/parent doesn't need drools). The work of cleaning unused dependencies can be done independently in any release. Basically the approach is: instead of integrate, we replicate and tidy up after.
It is proposed to use a mechanical & maintainable solution, for example using Maven dependency plugin. See https://www.baeldung.com/maven-unused-dependencies
Use maven dependency plugin to identify unused dependencies using
mvn dependency:analyzeSpecify used dependencies in the
<usedDependencies>section, as Maven can give false results, e.g. saying picocli is unused, when it is a runtime dependency, used for Liquibase rollback.Once sign-off is done by the team, re-run dependency analysis and remove any unused dependencies.
This process can be used on an ongoing basis as the decoupling work is done.
Future Dependency Uplifts
It is proposed that dependencies be auto-uplifted in future, e.g. using maven version plugin, or tools like Renovate or Dependabot. Currently, this is not feasible as changes to policy-parent do not trigger CSIT jobs for affected repos, meaning impacts are not known until later testing. Once dependencies are isolated to the clamp repo and CSITs run on every clamp code change, it becomes feasible to auto-uplift dependencies, preventing CVEs.
Release 2 - Spring Boot 4
Spring Boot 4 is needed for Spring Kafka to be compatible with Apache Kafka client 4.1, which was already delivered as a fix for stalled Kafka consumer issue.
Risk: A major uplift of Spring Boot carries a risk of breakage due to many dependency changes.
Mitigation: Separate release for Spring Boot uplift.
Release 3 - Spring Kafka: ACM-R only
Risk Implementation is being swapped out; Spring Kafka will certainly behave differently to policy-common message-bus. As such, there is some risk of bugs caused by behavioural differences.
Mitigation: Minimize risk by separating releases for Spring Kafka implementation for ACM-R and Participant Intermediary.
Risk: Spring Boot 3.5 does not (officially) support Apache Kafka client 4.1 - we need to either downgrade Kafka or uplift Spring Boot.
Mitigation: Uplift to Spring Boot 4 will be done first to ensure compatibility.
Release 4 - De-duplicating Spring & Logback configs
Risk: Some config may be inadvertently changed.
Mitigation: Compare the configs used before and after.
Refactoring Spring & Logback configurations to cleanup docker/helm charts and remove duplication. Some of these tasks could possibly be released with low risk items.
Release 5 - Spring Kafka: participant intermediary
Risk: Same as for ACM-R, however intermediary is used by multiple microservices, so the risk is magnified.
Mitigation: Spring Kafka for ACM-R is released in a previous release so any issues are detected before delivering Intermediary changes.
Risk: Version of Spring Kafka may rely on Spring Boot 4, so participants may need to uplift Spring Boot before Intermediary.
Mitigation: Additional study of compatibility recommended. Plenty of advanced notice for teams to uplift in advance.
Additional items that can be delivered in any release
Java Bean Validation
Risk: Low, given there is extensive test coverage using different service templates.
Mitigation: None needed, test coverage is solid.
Bean Validation is the only work item that depends on both policy-common and -models directly. As such, it is a high priority to remove, as it will block removal of policy-models.