Skip to content

Commit 45a97a3

Browse files
committed
Merge branch 'affinity-db-crud' into affinity-instance-integration
2 parents 931801d + 0e6eaf2 commit 45a97a3

File tree

8 files changed

+213
-209
lines changed

8 files changed

+213
-209
lines changed

flake.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -80,27 +80,13 @@
8080
mgVersion = openAPIVersion
8181
./tools/maghemite_mg_openapi_version;
8282

83-
8483
dendriteOpenAPI = downloadOpenAPI
8584
{
8685
repo = "dendrite";
8786
file = "dpd.json";
8887
version = dendriteVersion;
8988
};
9089

91-
ddmOpenAPI = downloadOpenAPI
92-
{
93-
repo = "maghemite";
94-
file = "ddm-admin.json";
95-
version = openAPIVersion ./tools/maghemite_ddm_openapi_version;
96-
};
97-
98-
mgOpenAPI = downloadOpenAPI
99-
{
100-
repo = "maghemite";
101-
file = "mg-admin.json";
102-
version = mgVersion;
103-
};
10490

10591
# given a list of strings of the form `PREFIX="SHA256"`, finds the string
10692
# starting with the provided `name` and returns the hash for that prefix.
@@ -409,9 +395,6 @@
409395
LIBCLANG_PATH = "${libclang.lib}/lib";
410396
OPENSSL_DIR = "${openssl.dev}";
411397
OPENSSL_LIB_DIR = "${openssl.out}/lib";
412-
413-
MG_OPENAPI_PATH = mgOpenAPI;
414-
DDM_OPENAPI_PATH = ddmOpenAPI;
415398
DPD_OPENAPI_PATH = dendriteOpenAPI;
416399

417400
# Needed by rustfmt-wrapper, see:

nexus/db-macros/outputs/project.txt

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,6 @@ pub enum Project<'a> {
1515
PrimaryKey(Root<'a>, Uuid),
1616
}
1717
impl<'a> Project<'a> {
18-
///Select a resource of type Disk within this Project, identified by its name
19-
pub fn disk_name<'b, 'c>(self, name: &'b Name) -> Disk<'c>
20-
where
21-
'a: 'c,
22-
'b: 'c,
23-
{
24-
Disk::Name(self, name)
25-
}
26-
///Select a resource of type Disk within this Project, identified by its name
27-
pub fn disk_name_owned<'c>(self, name: Name) -> Disk<'c>
28-
where
29-
'a: 'c,
30-
{
31-
Disk::OwnedName(self, name)
32-
}
33-
///Select a resource of type Instance within this Project, identified by its name
34-
pub fn instance_name<'b, 'c>(self, name: &'b Name) -> Instance<'c>
35-
where
36-
'a: 'c,
37-
'b: 'c,
38-
{
39-
Instance::Name(self, name)
40-
}
41-
///Select a resource of type Instance within this Project, identified by its name
42-
pub fn instance_name_owned<'c>(self, name: Name) -> Instance<'c>
43-
where
44-
'a: 'c,
45-
{
46-
Instance::OwnedName(self, name)
47-
}
4818
/// Fetch the record corresponding to the selected resource
4919
///
5020
/// This is equivalent to `fetch_for(authz::Action::Read)`.
@@ -393,3 +363,20 @@ impl<'a> Project<'a> {
393363
Ok((authz_silo, authz_project, db_row))
394364
}
395365
}
366+
impl<'a> Silo<'a> {
367+
///Select a resource of type Project within this Silo, identified by its name
368+
pub fn project_name<'b, 'c>(self, name: &'b Name) -> Project<'c>
369+
where
370+
'a: 'c,
371+
'b: 'c,
372+
{
373+
Project::Name(self, name)
374+
}
375+
///Select a resource of type Project within this Silo, identified by its name
376+
pub fn project_name_owned<'c>(self, name: Name) -> Project<'c>
377+
where
378+
'a: 'c,
379+
{
380+
Project::OwnedName(self, name)
381+
}
382+
}

nexus/db-macros/src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ mod test_helpers;
3232
/// lookup_resource! {
3333
/// name = "Organization",
3434
/// ancestors = [],
35-
/// children = [ "Project" ],
3635
/// lookup_by_name = true,
3736
/// soft_deletes = true,
3837
/// primary_key_columns = [ { column_name = "id", rust_type = Uuid } ]
@@ -52,7 +51,6 @@ mod test_helpers;
5251
/// lookup_resource! {
5352
/// name = "Organization",
5453
/// ancestors = [],
55-
/// children = [ "Project" ],
5654
/// lookup_by_name = true,
5755
/// soft_deletes = true,
5856
/// primary_key_columns = [ { column_name = "id", rust_type = Uuid } ]
@@ -61,7 +59,6 @@ mod test_helpers;
6159
/// lookup_resource! {
6260
/// name = "Instance",
6361
/// ancestors = [ "Organization", "Project" ],
64-
/// children = [],
6562
/// lookup_by_name = true,
6663
/// soft_deletes = true,
6764
/// primary_key_columns = [ { column_name = "id", rust_type = Uuid } ]
@@ -77,7 +74,6 @@ mod test_helpers;
7774
/// lookup_resource! {
7875
/// name = "Sled",
7976
/// ancestors = [ "Organization", "Project" ],
80-
/// children = [],
8177
/// lookup_by_name = true,
8278
/// soft_deletes = true,
8379
/// primary_key_columns = [ { column_name = "id", uuid_kind = SledType } ]

nexus/db-macros/src/lookup.rs

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ pub struct Input {
3434
/// with the top of the hierarchy
3535
/// (e.g., for an Instance, this would be `[ "Silo", "Project" ]`
3636
ancestors: Vec<String>,
37-
/// unordered list of resources that are direct children of this resource
38-
/// (e.g., for a Project, these would include "Instance" and "Disk")
39-
children: Vec<String>,
4037
/// whether lookup by name is supported (usually within the parent collection)
4138
lookup_by_name: bool,
4239
/// Description of the primary key columns
@@ -127,11 +124,6 @@ pub struct Config {
127124
/// [`authz_silo`, `authz_project`])
128125
path_authz_names: Vec<syn::Ident>,
129126

130-
// Child resources
131-
/// list of names of child resources, in the same form and with the same
132-
/// assumptions as [`Input::name`] (i.e., typically PascalCase)
133-
child_resources: Vec<String>,
134-
135127
// Parent resource, if any
136128
/// Information about the parent resource, if any
137129
parent: Option<Resource>,
@@ -160,7 +152,6 @@ impl Config {
160152
.collect();
161153
path_authz_names.push(resource.authz_name.clone());
162154

163-
let child_resources = input.children;
164155
let parent = input.ancestors.last().map(|s| Resource::for_name(s));
165156
let silo_restricted = !input.visible_outside_silo
166157
&& input.ancestors.iter().any(|s| s == "Silo");
@@ -177,7 +168,6 @@ impl Config {
177168
path_types,
178169
path_authz_names,
179170
parent,
180-
child_resources,
181171
lookup_by_name: input.lookup_by_name,
182172
primary_key_columns,
183173
soft_deletes: input.soft_deletes,
@@ -221,22 +211,22 @@ pub fn lookup_resource(
221211
let resource_name = &config.resource.name;
222212
let the_basics = generate_struct(&config);
223213
let misc_helpers = generate_misc_helpers(&config);
224-
let child_selectors = generate_child_selectors(&config);
214+
let child_selector = generate_child_selector(&config);
225215
let lookup_methods = generate_lookup_methods(&config);
226216
let database_functions = generate_database_functions(&config);
227217

228218
Ok(quote! {
229219
#the_basics
230220

231221
impl<'a> #resource_name<'a> {
232-
#child_selectors
233-
234222
#lookup_methods
235223

236224
#misc_helpers
237225

238226
#database_functions
239227
}
228+
229+
#child_selector
240230
})
241231
}
242232

@@ -287,63 +277,70 @@ fn generate_struct(config: &Config) -> TokenStream {
287277
}
288278
}
289279

290-
/// Generates the child selectors for this resource
280+
/// Generates the child selector for this resource's parent
291281
///
292-
/// For example, for the "Project" resource with child resources "Instance" and
293-
/// "Disk", this will generate the `Project::instance_name()` and
294-
/// `Project::disk_name()` functions.
295-
fn generate_child_selectors(config: &Config) -> TokenStream {
296-
let child_resource_types: Vec<_> =
297-
config.child_resources.iter().map(|c| format_ident!("{}", c)).collect();
298-
let child_selector_fn_names: Vec<_> = config
299-
.child_resources
300-
.iter()
301-
.map(|c| format_ident!("{}_name", heck::AsSnakeCase(c).to_string()))
302-
.collect();
303-
let child_selector_fn_names_owned: Vec<_> = config
304-
.child_resources
305-
.iter()
306-
.map(|c| {
307-
format_ident!("{}_name_owned", heck::AsSnakeCase(c).to_string())
308-
})
309-
.collect();
310-
let child_selector_fn_docs: Vec<_> = config
311-
.child_resources
312-
.iter()
313-
.map(|child| {
314-
format!(
315-
"Select a resource of type {} within this {}, \
316-
identified by its name",
317-
child, config.resource.name,
318-
)
319-
})
320-
.collect();
282+
/// For example, for the "Instance" resource with parent resource "Project",
283+
/// this will generate the `Project::instance_name()` and
284+
/// `Project::instance_name_owned()` functions.
285+
///
286+
/// This is generated by the child resource codegen, rather than by the parent
287+
/// resource codegen, since such functions are only generated for resources with
288+
/// `lookup_by_name = true`. Whether or not this is enabled for the child
289+
/// resource is not known when generating the parent resource code, so it's
290+
/// performed by the child instead.
291+
fn generate_child_selector(config: &Config) -> TokenStream {
292+
// If this resource cannot be looked up by name, we don't need to generate
293+
// child selectors on the parent resource.
294+
if !config.lookup_by_name {
295+
return quote! {};
296+
}
297+
298+
// The child selector is generated for the parent resource type. If there
299+
// isn't one, nothing to do here.
300+
let Some(ref parent) = config.parent else { return quote! {} };
301+
302+
let parent_resource_type = &parent.name;
303+
let child_selector_fn_name = format_ident!(
304+
"{}_name",
305+
heck::AsSnakeCase(config.resource.name.to_string()).to_string()
306+
);
307+
308+
let child_selector_fn_name_owned = format_ident!(
309+
"{}_name_owned",
310+
heck::AsSnakeCase(config.resource.name.to_string()).to_string()
311+
);
312+
let child_resource_type = &config.resource.name;
313+
314+
let child_selector_fn_docs = format!(
315+
"Select a resource of type {child_resource_type} within this \
316+
{parent_resource_type}, identified by its name",
317+
);
321318

322319
quote! {
323-
#(
320+
impl<'a> #parent_resource_type<'a> {
324321
#[doc = #child_selector_fn_docs]
325-
pub fn #child_selector_fn_names<'b, 'c>(
322+
pub fn #child_selector_fn_name<'b, 'c>(
326323
self,
327324
name: &'b Name
328-
) -> #child_resource_types<'c>
325+
) -> #child_resource_type<'c>
329326
where
330327
'a: 'c,
331328
'b: 'c,
332329
{
333-
#child_resource_types::Name(self, name)
330+
#child_resource_type::Name(self, name)
334331
}
335332

336333
#[doc = #child_selector_fn_docs]
337-
pub fn #child_selector_fn_names_owned<'c>(
334+
pub fn #child_selector_fn_name_owned<'c>(
338335
self,
339336
name: Name,
340-
) -> #child_resource_types<'c>
337+
) -> #child_resource_type<'c>
341338
where
342339
'a: 'c,
343340
{
344-
#child_resource_types::OwnedName(self, name)
341+
#child_resource_type::OwnedName(self, name)
345342
}
346-
)*
343+
}
347344
}
348345
}
349346

@@ -991,7 +988,6 @@ mod test {
991988
let output = lookup_resource(quote! {
992989
name = "Project",
993990
ancestors = ["Silo"],
994-
children = [ "Disk", "Instance" ],
995991
lookup_by_name = true,
996992
soft_deletes = true,
997993
primary_key_columns = [ { column_name = "id", rust_type = Uuid } ]
@@ -1002,7 +998,6 @@ mod test {
1002998
let output = lookup_resource(quote! {
1003999
name = "SiloUser",
10041000
ancestors = [],
1005-
children = [],
10061001
lookup_by_name = false,
10071002
soft_deletes = true,
10081003
primary_key_columns = [ { column_name = "id", rust_type = Uuid } ]
@@ -1013,7 +1008,6 @@ mod test {
10131008
let output = lookup_resource(quote! {
10141009
name = "Sled",
10151010
ancestors = [],
1016-
children = [],
10171011
lookup_by_name = false,
10181012
soft_deletes = true,
10191013
primary_key_columns = [ { column_name = "id", uuid_kind = SledKind } ]
@@ -1024,7 +1018,6 @@ mod test {
10241018
let output = lookup_resource(quote! {
10251019
name = "UpdateArtifact",
10261020
ancestors = [],
1027-
children = [],
10281021
lookup_by_name = false,
10291022
soft_deletes = false,
10301023
primary_key_columns = [

0 commit comments

Comments
 (0)