Add cloud-connector as a native foremanctl feature - #569
Conversation
| protocol = "grpc" | ||
| env = [ | ||
| "FORWARDER_USER={{ cloud_connector_user }}", | ||
| "FORWARDER_PASSWORD={{ cloud_connector_password }}", |
There was a problem hiding this comment.
This is the part we still need to work out how to properly handle, that is, the authentication.
There was a problem hiding this comment.
As I see it our options are
1 - Keep things as they are here, feeding admin/changeme to rhc - Not acceptable because the admin password ends up in the worker config.toml.
2 - Create a service user with limited permissions - Doable in the existing PRs here and in foreman_rh_cloud.
3 - Create a service user + personal access token and use that, same as the previous architecture - FAM doesn't have a module for personal access tokens, so this would be a fair bit of work
I think Option 2 seems promising and am pushing that update now.
There was a problem hiding this comment.
@ehelms Updated to use OAuth, but we still need the service user because yggdrasil-worker-forwarder only supports HTTP basic auth, and doesn't support OAuth.
|
Pushed updates addressing review feedback (1bfe640):
|
908e8b1 to
95a9cc9
Compare
2092035 to
84335ce
Compare
|
rebased & fixed conflicts |
qcjames53
left a comment
There was a problem hiding this comment.
I'm not enough in the loop to give this a full review but had a few comments that might be helpful. Consider this 80% good points 20% ass-talking. Here's what I was able to test directly:
- The iop conflict and missing consumer cert checks both work on the positive and negative cases (used manual subscription manager commands for the latter).
- The
yggdrasil-worker-forwardercheck works in the negative (was unable to figure out package install on centos9). - The cloud connector role works.
Beyond these tests, I have questions about the whole approach of cloud connector even after reading the planning docs and such.
- How are we splitting RHEL and Centos 9 deploys? I think the differentiation needs to be clearer since (best I can tell)
yggdrasil-worker-forwarderis RHEL only. If the packaged container images are centos9 and the rpms needed for cloud connector are RHEL-only, that seems like a big problem to me! deploy-devneeds to work with cloud connector. At minimum a procedure but ideally out of the box. I think we really need a procedure for setting up a centos9 deploy-dev environment to build/test cloud connector. If that's not possible, then we need a good procedure for setting up a RHEL environment as deploy-dev.- If it's possible to pass in subscription manager credentials safely, I would greatly prefer if we could deploy an environment with cloud connector immediately instead of requiring manual registration for the quadlet VM, THEN adding the feature. I understand this won't be an issue for customers but this would be HUGE for testing purposes.
I have to gracefully bow out of reviewing this for a few reasons: capacity + artemis stuff + this baby could come any day! Sorry to not complete testing but I put in an honest effort.
|
I'll respond with thoughts off the top of my head :)
In order for cloud connector to work you need available on your base system:
In the previous architecture, these weren't even listed as prerequisites, even in upstream docs. Downstream, you'd already have all of these since the Satellite system must be registered and have those repos enabled. But upstream, anything can happen. It seems this is a documentation gap. cc @Lennonka
I was testing with deploy-dev on RHEL (with |
|
@qcjames53 Addressed 2 comments and replied to the third |
|
Tested cloud connector feature in development mode. All core functionality works correctly. Found 3 necessary configuration changes for development environment. 🔍 Testing MethodologyEnvironment: Development mode using
🔗 Related/Dependent PRsForeman RH Cloud Plugin
Foremanctl Branch Preservation
Note: These PRs should be merged before or alongside this cloud connector feature PR. ✅ What Works1. Cloud Connector Deployment
Note: The cloud connector role does not install packages - it assumes 2. Service User AuthenticationCreated service user 3. API Endpoint VerificationManual test of Request: curl -u cloud_connector_user:$PASSWORD \
-X POST \
http://localhost:3000/api/v2/rh_cloud/cloud_request \
-H 'Content-Type: application/json' \
-d '{"directive":"foreman_rh_cloud", ...}'Result: 4. Configuration Validation
🔧 Required Code ChangesFound 3 necessary changes for development environment support: Change 1: Development URL ConfigurationFile: Issue: Development uses Rails dev server on port 3000, not containerized Foreman Fix: vars:
cloud_connector_url: "http://localhost:3000"
cloud_connector_admin_user: "{{ foreman_development_admin_user }}"
cloud_connector_admin_password: "{{ foreman_development_admin_password }}"Why: Points worker to the correct development Rails server endpoint Change 2: Disable Certificate Validation for HTTPFile: Issue: Development uses HTTP (no SSL), certificate validation fails Fix: - name: Create cloud connector service user
theforeman.foreman.user:
# ... existing parameters ...
validate_certs: false # <-- Add thisWhy: HTTP connections don't have valid certificates in development Change 3: Make CA Certificate Path OptionalFile: Issue: No CA certificate exists for HTTP connections, undefined variable error Fix: - name: Create cloud connector service user
theforeman.foreman.user:
# ... existing parameters ...
ca_path: "{{ foreman_ca_certificate | default(omit) }}" # <-- Change thisWhy: Prevents Ansible error when
|
|
Re: Change 1 - cloud_connector_url defaults to foreman_url which is https://{{ fqdn }}, Change 2 is not necessary unless I were to do Change 1, which I think is not needed for the reason above. Updating now with Change 3. |
|
Btw, Our role does install the packages — line 2-7 of tasks/main.yaml: - name: Install rhc and yggdrasil-worker-forwarder
ansible.builtin.package:
name:
- rhc
- yggdrasil-worker-forwarder |
|
/packit copr-build |
ekohl
left a comment
There was a problem hiding this comment.
Marking as request changes because I think this needs some fundamental things:
- Stop using
theforeman.foreman.setting - Resolve the registration task discussion
This no longer uses Added a new commit with the purpose-built module for announce to sources. Tested again and deploy succeeds, so I'm happy with it if you are. |
faa920c to
e5df4b7
Compare
|
rebased |
|
🍏 |
Re-implements the upstream satellite_operations.cloud_connector role natively in foremanctl so users can enable it via: foremanctl deploy --add-feature cloud-connector Feature overview: - Installs rhc and yggdrasil-worker-forwarder packages - Templates the worker config with FORWARDER_CA_FILE for explicit CA trust (requires yggdrasil-worker-forwarder >= 0.0.4) - Creates a dedicated service user with limited dispatch_cloud_requests permission for runtime worker authentication - Uses OAuth for all Foreman API calls during setup (role, user, settings), matching the pattern used by other foremanctl roles - Adds a reusable foremanctl_api custom module for OAuth-authenticated API calls where no FAM module exists - Sets rhc_instance_id and enables automatic inventory upload - Announces to Sources via the foreman_rh_cloud API - Optional HTTP proxy support via --cloud-connector-http-proxy - Pre-checks validate consumer certificate and iop mutual exclusion - Works with both foremanctl deploy and forge deploy-dev Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set worker script mode to 0755 (was 0750) to match test expectation and allow execution. Only remove the rhcd systemd drop-in directory when it is actually empty, preventing accidental deletion of files added by other roles or packages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace direct requests + requests_oauthlib usage with apypie's built-in OAuth1 support. This simplifies the code by leveraging existing OAuth1 implementation from the theforeman.foreman collection. Also removed the unnecessary status_code parameter from the module and cloud_connector task. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove tasks that should be handled by foreman_rh_cloud: - Role creation (seeded by foreman_rh_cloud) - Setting allow_auto_inventory_upload (defaults to true, shouldn't be overridden) Reorganize tests to use feature directory structure for auto-marking. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Ekohl asked for a purpose-built module for announce_to_sources instead of a generic "call any endpoint" module, so the call can properly wait for the resulting Foreman task rather than being best-effort. foremanctl_announce_to_sources uses apypie's resource_action/wait_for_task to poll the task to completion and fail loudly if it doesn't succeed. It also clears apypie's local apidoc cache before resolving the action, working around a case where the server's Apipie-Checksum header didn't change even though the action had been added to the live apidoc, which left the stale cached apidoc hiding the new action. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Use trailing commas instead of leading commas for the conditional FORWARDER_CA_FILE entry, per review feedback. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Per review feedback from ehelms: - Remove the static "changeme" password default; the real value is always auto-generated and persisted via vars/base.yaml, and a role invoked without that should fail loudly rather than fall back to a known password. - Use role-scoped variable names (cloud_connector_foreman_oauth_*, cloud_connector_foreman_ca_certificate) instead of consuming the global foreman_* vars directly in the role's tasks, matching the pattern used by backup, iop_core, and pulp. - Consolidate the HTTP proxy add/remove logic into http_proxy.yaml so it's all in one place. - Remove the cloud_connector_service_user override in vars/base.yaml since it was identical to the role default. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
e5df4b7 to
c5eb2f2
Compare
I realized this isn't entirely accurate - we did stop using it to set |
|
Found a way to make it even better, stand by |
foreman_rh_cloud's announce_to_sources action now accepts an instance_id param and sets Setting[:rhc_instance_id] itself before triggering the announcement task (it already required that setting to be non-blank and uses it as the rhc_id payload). This lets us drop the standalone theforeman.foreman.setting task and stop using that module in this role entirely. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
@ekohl Okay, found a way to not use |
Summary
satellite_operations.cloud_connectorrole natively in foremanctl (SAT-45966 / SAT-44641)cloud-connectorfeature gated behind--add-feature cloud-connector, withrh-clouddependencyrhcandyggdrasil-worker-forwarder, configures the worker, startsrhcd, setsrhc_instance_idvia the Foreman API, and announces to Sourcesforemanctl deployandforge deploy-devcloud_connector_userservice user with limiteddispatch_cloud_requestspermission for runtime worker authenticationforemanctl_apicustom module for OAuth-authenticated API calls where no FAM module existsiopfeature--cloud-connector-http-proxyflag for environments without direct internet accessCompanion PRs:
theforeman/foreman_rh_cloud#1214 (adds the
announce_to_sourcesAPI endpoint)theforeman/yggdrasil-worker-forwarder#5 (allows specifying a certificate to use)
Test plan
foremanctl deploy --add-feature cloud-connectorcompletes successfullyforemanctl features --list-enabledincludescloud-connectorsystemctl status rhcdshows active/running/etc/rhc/workers/foreman_rh_cloud.tomlhas correct content with service user credentialshammer settings info --name rhc_instance_idshows the consumer cert CNhammer user info --login cloud_connector_usershows the service user with Cloud Connector roleforemanctl deployis idempotentforge deploy-dev --add-feature cloud-connectorcompletes successfullycloud-connectorandiopfails early with a clear error🤖 Generated with Claude Code