dotnet-operator-sdk
dotnet-operator-sdk copied to clipboard
CRD generation fails for nested V1ObjectMeta
Describe the bug
The CRD for an entity that uses a V1PodTemplateSpec does not allow any metadata fields to be set on that property.
To Reproduce Given the following custom entity:
using k8s.Models;
using KubeOps.Operator.Entities;
using KubeOps.Operator.Entities.Annotations;
namespace MyNamespace
{
/// <summary>
/// MyEntity specification.
/// </summary>
public class V1Alpha1MyEntitySpec
{
/// <summary>
/// Gets or sets the pod template.
/// </summary>
[Required]
public V1PodTemplateSpec Template { get; set; }
}
/// <summary>
/// MyEntity status.
/// </summary>
public class V1Alpha1MyEntityStatus
{
}
/// <summary>
/// Definition of a MyEntity entity. This entity contains a specification of MyEntity instance.
/// </summary>
[KubernetesEntity(Kind = "MyEntity", Group = "my.group.com", ApiVersion = "v1alpha1")]
public class V1Alpha1MyEntity : CustomKubernetesEntity<V1Alpha1MyEntitySpec, V1Alpha1MyEntityStatus>
{
}
}
It generates this CRD:
...
template:
description: Gets or sets the pod template.
properties:
metadata:
type: object // Here I would expect properties to be defined.
spec:
properties:
activeDeadlineSeconds:
format: int64
nullable: true
type: integer
...
If I would modify and persist an instance of the above entity, like below, it will not persists the labels or any other properties.
var entity = new V1Alpha1MyEntity();
entity.Spec.Template.Metadata.Labels["foo"] = "bar";
...
Expected behavior A valid CRD that accepts metadata.
Additional context
When I modify the CRD to include x-kubernetes-preserve-unknown-fields: true, it works.
I believe it has to do with this part of the CRD generation, that may not hold for nested V1ObjectMeta's
Could you try with the "embedded resource" attribute? There is an attribute, that should be used if sub-resources are linked in properties (like deployments or other kubernetes elements) https://buehler.github.io/dotnet-operator-sdk/kube-ops/KubeOps.Operator.Entities.Annotations.EmbeddedResourceAttribute.html
public class V1Alpha1MyEntitySpec
{
/// <summary>
/// Gets or sets the pod template.
/// </summary>
[Required]
[EmbeddedResource]
public V1PodTemplateSpec Template { get; set; }
}
This should fix your error and is the intended way of using sub resources
That seems to do the trick, thanks!
Reopening this, because it doesn't seem to really 'solve' the issue.
When I add [EmbeddedResource], I now also have to specify apiVersion and kind properties. These are not defined for V1PodTemplateSpec (which is actually part of a V1Deployment).
Note that in my CRD example above, the property activeDeadlineSeconds is part of the V1PodTemplateSpec, and the CRD for that part is generated correctly. It's everything under metadata that is not.
I'm currently in an exam phase in my studies, as soon as this is over, I'm happy to analyze this matter.
Hey @basilfx
Im currently creating an operator that uses some similar feature. But I do reference a full Kubernetes object. In that case, the EmbeddedRessource is the correct way to go. If you want to have parts of the specification, you may need to use the [PreserveUnknownFields] attribute to set that accordingly.
But as you already mentioned this in the description, what would you expect from the CRD generator here?
Hi @buehler,
I'm not working on the project anymore (switched jobs).
However, what I would have expected, is that the properties under metadata are specified the same way as the properties under spec (on the same level) are. So you see that I only referenced public V1PodTemplateSpec Template { get; set; }, and it generated the spec sub-properties as expected, but the metadata properties not (it's just a type: object, nothing more).
Ah, I guess I get it. :-) Need to investigate again.
Hey, didn't want to create a separate issue, but I think it's related to this one. I've upgraded from 6.0.18 to the latest version (6.2.13). When using V1ResourceRequirements or some type that uses that built-in (for example in my case V1PersistentVolumeClaimSpec) type, the schema gets generated a bit differently and I can't use my sample.
The sample resource has the following value:
nodes:
- name: "node-1"
productionVolumeClaimTemplate:
accessModes:
- "ReadWriteOnce"
storageClassName: "ceph-fs"
resources:
requests:
storage: 10Gi
The generated CRD for the volume claim template:
productionVolumeClaimTemplate:
properties:
...
resources:
properties:
limits:
additionalProperties:
properties:
format:
enum:
- DecimalExponent
- BinarySI
- DecimalSI
type: string
value:
type: string
type: object
type: object
requests:
additionalProperties:
properties:
format:
enum:
- DecimalExponent
- BinarySI
- DecimalSI
type: string
value:
type: string
type: object
type: object
type: object
And when applying the sample resource, it gives the following error:
.resources.requests.storage: Invalid value: "string": productionVolumeClaimTemplate.resources.requests.storage in body must be of type object: "string"
In version 6.0.18, on the resource's limits and requests properties it generated just:
type: object
x-kubernetes-preserve-unknown-fields: true
Sorry for the mile-long text and thanks for making the awesome lib!