diff --git a/scripts/replicated_deploy.sh b/scripts/replicated_deploy.sh index c353bef5..53a4ef34 100755 --- a/scripts/replicated_deploy.sh +++ b/scripts/replicated_deploy.sh @@ -208,9 +208,12 @@ else done [ -n "$META" ] || fail "upgrade service never came up" - # --- config: read values, write them straight back ----------------------- + # --- config: read values, write them back -------------------------------- + # These instances exist for the E2E suite. Its org specs provision users via + # the endpoint that oem_user_creation_flow_enabled registers (off by default). if [ "$(jq -r .isConfigurable <<<"$META")" = true ]; then - TMO=60 api "$UP/config" | jq -c '{configGroups}' >/tmp/cfg.json + TMO=60 api "$UP/config" | jq -c '{configGroups} + | (.configGroups[]?.items[]? | select(.name == "oem_user_creation_flow_enabled") | .value) = "1"' >/tmp/cfg.json R="$(retry_gateway PUT --data-binary @/tmp/cfg.json "$UP/config" || true)" ok <<<"$R" || fail "config rejected: $(why <<<"$R") — new release likely added a required item with no default" fi diff --git a/scripts/test_replicated_deploy.py b/scripts/test_replicated_deploy.py index 61b60464..2fd64894 100644 --- a/scripts/test_replicated_deploy.py +++ b/scripts/test_replicated_deploy.py @@ -47,6 +47,8 @@ def reply(self, code, obj): def do_PUT(self): state["config_paths"].append(self.path) + n = int(self.headers.get("Content-Length") or 0) + state["config_bodies"].append(json.loads(self.rfile.read(n) or b"null")) total = len(state["config_paths"]) if state["config_502_then"] and total <= state["config_502_then"]: return self.reply(502, None) @@ -102,6 +104,8 @@ def do_GET(self): res = {"results": [{"isPass": not strict, "title": "mem"}]} return self.reply(200, {"preflightResult": { "result": json.dumps(res), "hasFailingStrictPreflights": strict}}) + if p.endswith("/upgrade-service/app/openhands/config"): + return self.reply(200, {"configGroups": state["config_groups"]}) if "/task/upgrade-service" in p: return self.reply(200, {"status": ""}) if p.endswith("/upgrade-service/app/openhands"): @@ -121,7 +125,8 @@ def kots(): "placeholders": 0, "strict_fail": False, "deploy_status": 200, "deploy_body": None, "deploy_502_then": 0, "deploy_paths": [], "config_status": 200, "config_body": None, "config_502_then": 0, - "config_paths": [], "boot_status": 200, "boot_body": None, + "config_paths": [], "config_bodies": [], "config_groups": None, + "boot_status": 200, "boot_body": None, "boot_502_then": 0, "boot_paths": [], "apps_status": 200, "configurable": False, "apps_fail_after_deploy": False, "apps_dark": False, "current_status": "deployed", "extra_env": {}} @@ -265,6 +270,19 @@ def test_a_transient_502_on_the_config_put_is_retried(kots): assert kots["deploy_paths"], "a retried config must not block the deploy" +def test_the_config_write_back_enables_user_provisioning_and_keeps_other_values(kots): + """The E2E org specs call the provision-user endpoint, which this item registers.""" + kots["configurable"] = True + kots["config_groups"] = [{"name": "oem", "items": [ + {"name": "oem_user_creation_flow_enabled", "value": "", "default": "0"}, + {"name": "other_item", "value": "kept", "default": ""}]}] + r = kots["run"]() + assert r.returncode == 0, r.stderr + assert kots["config_bodies"][-1] == {"configGroups": [{"name": "oem", "items": [ + {"name": "oem_user_creation_flow_enabled", "value": "1", "default": "0"}, + {"name": "other_item", "value": "kept", "default": ""}]}]} + + def test_a_transient_502_on_booting_the_upgrade_service_is_retried(kots): """start-upgrade-service goes through the same gateway restart window.""" kots["boot_502_then"] = 1