Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions control_plane/contracts/lane_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ class LaunchplaneLaneSummary(BaseModel):

@model_validator(mode="after")
def _populate_provider_neutral_target(self) -> "LaunchplaneLaneSummary":
if self.provider_target is None:
if self.dokploy_target is not None and self.dokploy_target_id is not None:
self.provider_target = ProviderTargetRecord.from_dokploy_records(
target_record=self.dokploy_target,
target_id_record=self.dokploy_target_id,
)
if self.deployed_target is None and self.latest_deployment is not None:
self.deployed_target = self.latest_deployment.deployed_target
return self
20 changes: 1 addition & 19 deletions control_plane/contracts/product_environment_read_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1716,25 +1716,7 @@ def _target_summary(lane_summary: LaunchplaneLaneSummary | None) -> ProductTarge
else "",
trust_state="recorded",
)
if lane_summary.dokploy_target is None:
return ProductTargetSummary(
artifact_manifest=lane_summary.artifact_manifest,
expected_runtime_identity=expected_identity,
observed_runtime_identity=destination_health.observed_runtime_identity
if destination_health is not None
else None,
runtime_identity_status=destination_health.runtime_identity_status
if destination_health is not None
else "unchecked",
runtime_identity_detail=destination_health.runtime_identity_detail
if destination_health is not None
else "",
trust_state=lane_summary.provenance.freshness_status,
)
return ProductTargetSummary(
target_type=lane_summary.dokploy_target.target_type,
target_name=lane_summary.dokploy_target.target_name,
target_id_recorded=lane_summary.dokploy_target_id is not None,
artifact_manifest=lane_summary.artifact_manifest,
expected_runtime_identity=expected_identity,
observed_runtime_identity=destination_health.observed_runtime_identity
Expand All @@ -1746,7 +1728,7 @@ def _target_summary(lane_summary: LaunchplaneLaneSummary | None) -> ProductTarge
runtime_identity_detail=destination_health.runtime_identity_detail
if destination_health is not None
else "",
trust_state="recorded",
trust_state="missing",
)


Expand Down
42 changes: 28 additions & 14 deletions control_plane/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -8121,6 +8121,7 @@ def create_launchplane_service_app(
resolved_ingress_provider_factory = ingress_provider_factory
if resolved_ingress_provider_factory is None:
if npmplus_ingress_client_factory is not None:

def npmplus_ingress_provider_from_client_factory() -> IngressProvider:
return NpmplusIngressProvider(client=npmplus_ingress_client_factory())

Expand Down Expand Up @@ -11913,12 +11914,14 @@ def product_action_allowed(
authz_policy = updated_policy
resolved_authz_policy_sha256 = authz_policy_record.policy_sha256
resolved_authz_policy_source = "db"
result, driver_result = control_plane_authz_grant_service.build_authz_policy_github_actions_removal_service_result(
authz_policy_record=authz_policy_record,
changed=changed,
mode=authz_removal_request.mode,
diff=diff,
audit=audit,
result, driver_result = (
control_plane_authz_grant_service.build_authz_policy_github_actions_removal_service_result(
authz_policy_record=authz_policy_record,
changed=changed,
mode=authz_removal_request.mode,
diff=diff,
audit=audit,
)
)
elif path == "/v1/authz-policies/github-humans/grants":
human_authz_grant_request = control_plane_authz_grant_service.AuthzPolicyGitHubHumanGrantEnvelope.model_validate(
Expand Down Expand Up @@ -12613,9 +12616,7 @@ def product_action_allowed(
)
)
elif path == PROVIDER_TARGET_OPERATIONS_ROUTE:
provider_target_request = ProviderTargetOperationEnvelope.model_validate(
payload
)
provider_target_request = ProviderTargetOperationEnvelope.model_validate(payload)
if not isinstance(record_store, PostgresRecordStore):
return _json_response(
start_response=start_response,
Expand Down Expand Up @@ -12665,13 +12666,28 @@ def product_action_allowed(
"error": {
"code": "authorization_denied",
"message": (
"Workflow cannot run Launchplane provider-target"
" operations."
"Workflow cannot run Launchplane provider-target operations."
),
},
},
)
if provider_target_request.mode == "backfill-apply":
if not request_idempotency_key:
return _json_response(
start_response=start_response,
status_code=400,
payload={
"status": "rejected",
"trace_id": request_trace_id,
"error": {
"code": "idempotency_key_required",
"message": (
"Provider-target backfill apply requests require"
" an Idempotency-Key header."
),
},
},
)
idempotent_response = _check_idempotent_request(
record_store=record_store,
scope=request_scope,
Expand All @@ -12687,9 +12703,7 @@ def product_action_allowed(
record_store=record_store,
request=provider_target_request,
)
assert isinstance(
provider_target_result, ProviderTargetOperationRouteResult
)
assert isinstance(provider_target_result, ProviderTargetOperationRouteResult)
result = provider_target_result.result
driver_result = provider_target_result.driver_result
elif path == "/v1/drivers/launchplane/self-deploy":
Expand Down
66 changes: 12 additions & 54 deletions control_plane/storage/postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -3144,73 +3144,31 @@ def list_dokploy_target_records(self) -> tuple[DokployTargetRecord, ...]:
def read_provider_target_record(
self, *, context_name: str, instance_name: str
) -> ProviderTargetRecord:
record = self._read_optional_model(
return self._read_model(
model_type=ProviderTargetRecord,
orm_model=LaunchplaneProviderTargetRow,
filters=(
LaunchplaneProviderTargetRow.context == context_name,
LaunchplaneProviderTargetRow.instance == instance_name,
),
)
if record is not None:
return record
target_record = self.read_dokploy_target_record(
context_name=context_name,
instance_name=instance_name,
)
target_id_record = self.read_dokploy_target_id_record(
context_name=context_name,
instance_name=instance_name,
)
return ProviderTargetRecord.from_dokploy_records(
target_record=target_record,
target_id_record=target_id_record,
)

def list_provider_target_records(
self, *, provider_id: str = ""
) -> tuple[ProviderTargetRecord, ...]:
normalized_provider_id = provider_id.strip().lower()
all_physical_records = list(
self._list_models(
model_type=ProviderTargetRecord,
orm_model=LaunchplaneProviderTargetRow,
order_by=(
LaunchplaneProviderTargetRow.context.asc(),
LaunchplaneProviderTargetRow.instance.asc(),
),
)
filters: Sequence[object] = ()
if normalized_provider_id:
filters = (LaunchplaneProviderTargetRow.provider_id == normalized_provider_id,)
return self._list_models(
model_type=ProviderTargetRecord,
orm_model=LaunchplaneProviderTargetRow,
filters=filters,
order_by=(
LaunchplaneProviderTargetRow.context.asc(),
LaunchplaneProviderTargetRow.instance.asc(),
),
)
physical_record_keys = {
(record.context, record.instance) for record in all_physical_records
}
physical_records = list(
record
for record in all_physical_records
if not normalized_provider_id or record.provider_id == normalized_provider_id
)
target_id_records = {
(record.context, record.instance): record
for record in self.list_dokploy_target_id_records()
}
provider_records: list[ProviderTargetRecord] = [*physical_records]
for target_record in self.list_dokploy_target_records():
if (target_record.context, target_record.instance) in physical_record_keys:
continue
target_id_record = target_id_records.get(
(target_record.context, target_record.instance)
)
if target_id_record is None:
continue
provider_record = ProviderTargetRecord.from_dokploy_records(
target_record=target_record,
target_id_record=target_id_record,
)
if normalized_provider_id and provider_record.provider_id != normalized_provider_id:
continue
provider_records.append(provider_record)
provider_records.sort(key=lambda record: (record.context, record.instance))
return tuple(provider_records)

def list_physical_provider_target_records(self) -> tuple[ProviderTargetRecord, ...]:
return self._list_models(
Expand Down
11 changes: 5 additions & 6 deletions control_plane/workflows/generic_web_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,7 @@ def _validate_context(self) -> "GenericWebPostDeployContext":
raise ValueError("generic web post-deploy context requires instance")
if not self.deployment_record_id.strip():
raise ValueError("generic web post-deploy context requires deployment_record_id")
self.target_category = cast(
DeployTargetCategory, self.target_category.strip().lower()
)
self.target_category = cast(DeployTargetCategory, self.target_category.strip().lower())
self.provider_id = self.provider_id.strip().lower()
self.provider_target_type = self.provider_target_type.strip().lower()
self.target_type = self.target_type.strip().lower()
Expand Down Expand Up @@ -326,6 +324,7 @@ def _fallback_ship_request(
def _resolve_deploy_target(
*,
control_plane_root: Path,
record_store: GenericWebDeployStore,
request: GenericWebDeployRequest,
profile: LaunchplaneProductProfileRecord,
lane: ProductLaneProfile,
Expand All @@ -337,6 +336,7 @@ def _resolve_deploy_target(
request_source_git_ref=request.source_git_ref,
request_timeout_seconds=request.timeout_seconds,
request_no_cache=request.no_cache,
record_store=record_store,
profile=profile,
lane=lane,
normalized_artifact_id=normalize_generic_web_artifact_id(
Expand Down Expand Up @@ -381,6 +381,7 @@ def execute_generic_web_deploy(
try:
resolved_deploy_target = _resolve_deploy_target(
control_plane_root=control_plane_root,
record_store=record_store,
request=request,
profile=resolved_profile,
lane=resolved_lane,
Expand Down Expand Up @@ -486,9 +487,7 @@ def execute_generic_web_deploy(
updated_at=finished_at,
)
)
target_fields = _deploy_result_target_fields(
resolved_deploy_target=resolved_deploy_target
)
target_fields = _deploy_result_target_fields(resolved_deploy_target=resolved_deploy_target)
return GenericWebDeployResult(
deployment_record_id=record_id,
deploy_status=deployment_status,
Expand Down
Loading