Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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
24 changes: 15 additions & 9 deletions backend/infrahub/core/schema/schema_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@

log = get_logger()

profiles_rel_settings: dict[str, Any] = {
"name": "profiles",
"identifier": PROFILE_NODE_RELATIONSHIP_IDENTIFIER,
"peer": InfrahubKind.PROFILE,
"kind": RelationshipKind.PROFILE,
"cardinality": RelationshipCardinality.MANY,
"branch": BranchSupportType.AWARE,
}


class SchemaBranch:
def __init__(
Expand Down Expand Up @@ -1933,15 +1942,6 @@ def manage_profile_relationships(self) -> None:
):
continue

profiles_rel_settings: dict[str, Any] = {
"name": "profiles",
"identifier": PROFILE_NODE_RELATIONSHIP_IDENTIFIER,
"peer": InfrahubKind.PROFILE,
"kind": RelationshipKind.PROFILE,
"cardinality": RelationshipCardinality.MANY,
"branch": BranchSupportType.AWARE,
}

# Add relationship between node and profile
if "profiles" not in node.relationship_names:
node_schema = self.get(name=node_name, duplicate=True)
Expand Down Expand Up @@ -2136,6 +2136,12 @@ def add_relationships_to_template(self, node: NodeSchema | GenericSchema) -> Non
template_schema.human_friendly_id = [parent_hfid] + template_schema.human_friendly_id
template_schema.uniqueness_constraints[0].append(relationship.name)

if getattr(node, "generate_profile", False) and getattr(node, "generate_template", False):
if "profiles" not in [r.name for r in template_schema.relationships]:
template_schema.relationships.append(RelationshipSchema(**profiles_rel_settings))

self.set(name=template_schema.kind, schema=template_schema)

def generate_object_template_from_node(
self, node: NodeSchema | GenericSchema, need_templates: set[NodeSchema | GenericSchema]
) -> TemplateSchema | GenericSchema:
Expand Down
8 changes: 7 additions & 1 deletion backend/infrahub/profiles/node_applier.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from infrahub.core.attribute import BaseAttribute
from infrahub.core.branch import Branch
from infrahub.core.node import Node
from infrahub.core.schema import TemplateSchema
from infrahub.database import InfrahubDatabase

from .queries.get_profile_data import GetProfileDataQuery, ProfileData
Expand All @@ -29,7 +30,12 @@ async def _get_attr_names_for_profiles(self, node: Node) -> list[str]:
for attr_schema in node_schema.attributes:
attr_name = attr_schema.name
node_attr: BaseAttribute = getattr(node, attr_name)
if node_attr.is_from_profile or node_attr.is_default:
is_template = None
if node_attr.source_id:
await node_attr.get_source(db=self.db)
if isinstance(node_attr.source.get_schema(), TemplateSchema):
is_template = True
if node_attr.is_from_profile or node_attr.is_default or is_template:
Comment on lines +33 to +38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean that profile values will override template values? if so, that's not what I would expect, but maybe you could explain what the expected behavior is in the PR description

I would think that template values would take precedence over profile values. and I'd think that adding the profiles relationship to a template would be enough and this change to NodeProfilesApplier wouldn't be necessary, but I could definitely be missing something

attr_names_for_profiles.append(attr_name)
return attr_names_for_profiles

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { jsonToGraphQLQuery } from "json-to-graphql-query";
import { addAttributesToRequest, addRelationshipsToRequest } from "@/shared/api/graphql/utils";
import { getRelationshipsForForm } from "@/shared/components/form/utils/getRelationshipsForForm";

import { getSchema } from "@/entities/schema/domain/get-schema";
import type { NodeSchema, ProfileSchema } from "@/entities/schema/types";

export const generateObjectEditFormQuery = ({
Expand All @@ -12,6 +13,10 @@ export const generateObjectEditFormQuery = ({
schema: NodeSchema | ProfileSchema;
objectId: string;
}): string => {
let parentSchema: NodeSchema | ProfileSchema | undefined;
if (schema.kind && schema.kind.includes("Template")) {
parentSchema = getSchema(schema.name).schema;
}
const request = {
query: {
__name: "GetObjectForEditForm",
Expand All @@ -32,7 +37,8 @@ export const generateObjectEditFormQuery = ({
getRelationshipsForForm(schema.relationships ?? [], true, schema),
{ withMetadata: true }
),
...("generate_profile" in schema && schema.generate_profile
...(("generate_profile" in schema && schema.generate_profile) ||
(parentSchema && "generate_profile" in parentSchema && parentSchema.generate_profile)
? {
profiles: {
edges: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,15 @@ export default function ObjectTemplateForm({
}

if (selectedObjectTemplate !== undefined) {
return <ObjectForm {...props} objectTemplate={selectedObjectTemplate} />;
return (
<ObjectForm
{...props}
currentProfiles={
selectedObjectTemplate?.profiles?.edges?.map((edge: any) => edge?.node) ?? []
}
objectTemplate={selectedObjectTemplate}
/>
);
}

return (
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/src/shared/components/form/object-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export interface ObjectFormProps extends Omit<DynamicFormProps, "fields" | "onSu
}

const ObjectForm = ({ kind, currentProfiles, ...props }: ObjectFormProps) => {
const { schema, isNode, isGeneric } = useSchema(kind);
const { schema, isNode, isGeneric, isTemplate } = useSchema(kind);

if (!schema) {
return (
Expand Down Expand Up @@ -148,7 +148,7 @@ const ObjectForm = ({ kind, currentProfiles, ...props }: ObjectFormProps) => {
);
}

if (isNode && schema.generate_profile) {
if ((isNode && schema.generate_profile) || isTemplate) {
return <NodeWithProfileForm schema={schema} profiles={currentProfiles} {...props} />;
}

Expand Down
16 changes: 8 additions & 8 deletions frontend/app/src/shared/components/form/profiles-selector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { gql } from "@apollo/client";
import { Icon } from "@iconify-icon/react";
import { useAtomValue } from "jotai/index";
import { useEffect, useId } from "react";
import { useId } from "react";

import useQuery from "@/shared/api/graphql/useQuery";
import { Button } from "@/shared/components/buttons/button-primitive";
Expand Down Expand Up @@ -42,12 +42,6 @@ export const ProfilesSelector = ({
}: ProfilesSelectorProps) => {
const id = useId();

useEffect(() => {
if (!value && defaultValue) {
onChange(defaultValue);
}
}, [defaultValue]);

const genericSchemas = useAtomValue(genericSchemasAtom);
const profileSchemas = useAtomValue(profileSchemasAtom);

Expand All @@ -70,7 +64,9 @@ export const ProfilesSelector = ({
const profilesList = kindList
.map((profile) => {
// Get the profile schema for the current kind
const profileSchema = profileSchemas.find((profileSchema) => profileSchema.name === profile);
const profileSchema = profileSchemas.find(
(profileSchema) => profileSchema.name === profile?.replace("Template", "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why we need profile?.replace("Template", "")?

);

// Get attributes for query + form data
const attributes = getObjectAttributes({ schema: profileSchema, forProfiles: true });
Expand Down Expand Up @@ -114,6 +110,10 @@ export const ProfilesSelector = ({
[]
);

if (!value && defaultValue) {
onChange(profiles.filter((profile) => defaultValue.some((def) => def.id === profile.id)));
}

if (!profiles || profiles.length === 0) return null;

const selectedValues = value ?? [];
Expand Down
Loading