1212from sqlmodel import col , select
1313from sqlmodel .ext .asyncio .session import AsyncSession
1414
15- from ...common .enums import ManifestKind
1615from ...common .jsonpatch import JSONPatch , JSONPatchError , apply_json_patch
1716from ...common .logging import LOGGER
1817from ...db .campaigns_v2 import Campaign , Manifest , _default_campaign_namespace
19- from ...db .manifests_v2 import ManifestWrapper
18+ from ...db .manifests_v2 import ManifestModel
2019from ...db .session import db_session_dependency
2120
2221# TODO should probably bind a logger to the fastapi app or something
@@ -103,39 +102,23 @@ async def read_single_resource(
103102 summary = "Add a manifest resource" ,
104103 status_code = 204 ,
105104)
106- async def create_one_or_more_resources (
105+ async def create_one_or_more_manifests (
107106 request : Request ,
108107 response : Response ,
109108 session : Annotated [AsyncSession , Depends (db_session_dependency )],
110- manifests : ManifestWrapper | list [ManifestWrapper ],
109+ manifests : ManifestModel | list [ManifestModel ],
111110) -> None :
112- # TODO should support query parameters that scope the namespace, such that
113- # response headers from a campaign-create operation can immediately
114- # follow a link to node-create for that campaign.
115-
116111 # We could be given a single manifest or a list of them. In the singleton
117112 # case, wrap it in a list so we can treat everything equally
118113 if not isinstance (manifests , list ):
119114 manifests = [manifests ]
120115
121116 for manifest in manifests :
122- # Validate the input by checking the "kind" of manifest.
123- # The difference between a "manifest" and a "node" is iffy, but all we
124- # want to assert here is that nodes, campaigns, and edges don't go in
125- # the manifest table
126- if manifest .kind in [ManifestKind .campaign , ManifestKind .node , ManifestKind .edge ]:
127- raise HTTPException (status_code = 422 , detail = f"Manifests may not be a { manifest .kind .name } kind." )
128-
129- # and that the manifest includes any required fields, though this could
130- # just as well be a try/except ValueError around `_.model_validate()`
131- elif (_name := manifest .metadata_ .pop ("name" , None )) is None :
132- raise HTTPException (status_code = 400 , detail = "Manifests must have a name set in '.metadata.name'" )
133-
134- # TODO match node with jsonschema and validate
117+ _name = manifest .metadata_ .name
135118
136119 # A manifest must exist in the namespace of an existing campaign
137120 # or the default namespace
138- _namespace : str | None = manifest .metadata_ .pop ( " namespace" , None )
121+ _namespace : str | None = manifest .metadata_ .namespace
139122 if _namespace is None :
140123 _namespace_uuid = _default_campaign_namespace
141124 else :
@@ -153,9 +136,8 @@ async def create_one_or_more_resources(
153136 raise HTTPException (status_code = 422 , detail = "Requested namespace does not exist." )
154137 _namespace_uuid = _campaign_id
155138
156- # A node must be a new version if name+namespace already exists
157- # - check db for node as name+namespace, get version and increment
158- _version = int (manifest .metadata_ .pop ("version" , 0 ))
139+ # A manifest must be a new version if name+namespace already exists
140+ # check db for manifest as name+namespace, get version and increment
159141
160142 s = (
161143 select (Manifest )
@@ -164,18 +146,18 @@ async def create_one_or_more_resources(
164146 .order_by (col (Manifest .version ).desc ())
165147 .limit (1 )
166148 )
167- _previous = (await session .exec (s )).one_or_none ()
168149
169- _version = _previous .version if _previous else _version
150+ _previous = (await session .exec (s )).one_or_none ()
151+ _version = _previous .version if _previous else manifest .metadata_ .version
170152 _version += 1
171153 _manifest = Manifest (
172154 id = uuid5 (_namespace_uuid , f"{ _name } .{ _version } " ),
173155 name = _name ,
174156 namespace = _namespace_uuid ,
175157 kind = manifest .kind ,
176158 version = _version ,
177- metadata_ = manifest .metadata_ ,
178- spec = manifest .spec ,
159+ metadata_ = manifest .metadata_ . model_dump () ,
160+ spec = manifest .spec . model_dump () ,
179161 )
180162
181163 # Put the node in the database
@@ -214,7 +196,7 @@ async def update_manifest_resource(
214196 - This API always targets the latest version of a manifest when applying
215197 a patch. This requires and maintains a "linear" sequence of versions;
216198 it is not permissible to "patch" a previous version and create a "tree"-
217- like history of manifests. For exmaple , every manifest may be diffed
199+ like history of manifests. For example , every manifest may be diffed
218200 against any previous version without having to consider branches.
219201 """
220202 use_rfc6902 = False
0 commit comments