Skip to content

Commit 7498304

Browse files
author
Christoph Bühler
committed
fix: remove required field from crd when zero
This fixes #19.
1 parent d15c94e commit 7498304

File tree

3 files changed

+234
-3
lines changed

3 files changed

+234
-3
lines changed

src/KubeOps/Operator/Entities/Extensions/EntityToCrdExtensions.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Generic;
4-
using System.ComponentModel.DataAnnotations;
53
using System.Linq;
64
using System.Reflection;
75
using k8s;
86
using k8s.Models;
97
using KubeOps.Operator.Entities.Annotations;
108
using Namotion.Reflection;
11-
using RequiredAttribute = KubeOps.Operator.Entities.Annotations.RequiredAttribute;
129

1310
namespace KubeOps.Operator.Entities.Extensions
1411
{
@@ -187,6 +184,10 @@ private static V1JSONSchemaProps MapType(Type type)
187184
.Where(prop => prop.GetCustomAttribute<RequiredAttribute>() != null)
188185
.Select(prop => CamelCase(prop.Name))
189186
.ToList();
187+
if (props.Required.Count == 0)
188+
{
189+
props.Required = null;
190+
}
190191
}
191192
else if (type == typeof(int) || Nullable.GetUnderlyingType(type) == typeof(int))
192193
{

tests/KubeOps.Test/Operator/Entities/CrdGeneration.Test.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,5 +209,14 @@ public void Should_Set_Required()
209209
var specProperties = crd.Spec.Versions.First().Schema.OpenAPIV3Schema.Properties["spec"];
210210
specProperties.Required.Should().Contain("required");
211211
}
212+
213+
[Fact]
214+
public void Should_Set_Required_Null_If_No_Required()
215+
{
216+
var crd = EntityToCrdExtensions.CreateCrd(_testStatusEntity);
217+
218+
var specProperties = crd.Spec.Versions.First().Schema.OpenAPIV3Schema.Properties["spec"];
219+
specProperties.Required.Should().BeNull();
220+
}
212221
}
213222
}
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
using System;
2+
using FluentAssertions;
3+
using k8s.Models;
4+
using KubeOps.Operator.Entities.Extensions;
5+
using KubeOps.Test.Operator.Entities.TestEntities;
6+
using Xunit;
7+
8+
namespace KubeOps.Test.Operator.Entities
9+
{
10+
public class V1CustomResourceDefinitionConvertTest
11+
{
12+
private readonly Type _testSpecEntity = typeof(TestSpecEntity);
13+
private readonly Type _testStatusEntity = typeof(TestStatusEntity);
14+
15+
[Fact]
16+
public void Should_Correctly_Translate_CRD()
17+
{
18+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
19+
var ced = CustomEntityDefinitionExtensions.CreateResourceDefinition(_testSpecEntity);
20+
21+
crd.Kind.Should().Be(V1CustomResourceDefinition.KubeKind);
22+
crd.Metadata.Name.Should().Be($"{ced.Plural}.{ced.Group}");
23+
crd.Spec.Names.Kind.Should().Be(ced.Kind);
24+
crd.Spec.Names.ListKind.Should().Be(ced.ListKind);
25+
crd.Spec.Names.Singular.Should().Be(ced.Singular);
26+
crd.Spec.Names.Plural.Should().Be(ced.Plural);
27+
crd.Spec.Scope.Should().Be(ced.Scope.ToString());
28+
}
29+
30+
[Fact]
31+
public void Should_Add_Status_SubResource_If_Present()
32+
{
33+
var crd = EntityToCrdExtensions.CreateCrd(_testStatusEntity).Convert();
34+
crd.Spec.Subresources.Status.Should().NotBeNull();
35+
}
36+
37+
[Fact]
38+
public void Should_Not_Add_Status_SubResource_If_Absent()
39+
{
40+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
41+
crd.Spec.Subresources?.Status?.Should().BeNull();
42+
}
43+
44+
[Theory]
45+
[InlineData("Int", "integer", "int32")]
46+
[InlineData("Long", "integer", "int64")]
47+
[InlineData("Float", "number", "float")]
48+
[InlineData("Double", "number", "double")]
49+
[InlineData("String", "string", null)]
50+
[InlineData("Bool", "boolean", null)]
51+
[InlineData("DateTime", "string", "date-time")]
52+
[InlineData("Enum", "string", null)]
53+
public void Should_Set_The_Correct_Type_And_Format_For_Types(string fieldName, string typeName, string? format)
54+
{
55+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
56+
57+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
58+
specProperties.Type.Should().Be("object");
59+
60+
var normalField = specProperties.Properties[$"normal{fieldName}"];
61+
normalField.Type.Should().Be(typeName);
62+
normalField.Format.Should().Be(format);
63+
normalField.Nullable.Should().BeNull();
64+
65+
var nullableField = specProperties.Properties[$"nullable{fieldName}"];
66+
nullableField.Type.Should().Be(typeName);
67+
nullableField.Format.Should().Be(format);
68+
nullableField.Nullable.Should().BeTrue();
69+
}
70+
71+
[Fact]
72+
public void Should_Set_The_Correct_Array_Type()
73+
{
74+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
75+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
76+
77+
var normalField = specProperties.Properties["stringArray"];
78+
normalField.Type.Should().Be("array");
79+
(normalField.Items as V1JSONSchemaProps)?.Type?.Should().Be("string");
80+
normalField.Nullable.Should().BeNull();
81+
82+
var nullableField = specProperties.Properties["nullableStringArray"];
83+
nullableField.Type.Should().Be("array");
84+
(nullableField.Items as V1JSONSchemaProps)?.Type?.Should().Be("string");
85+
nullableField.Nullable.Should().BeTrue();
86+
}
87+
88+
[Fact]
89+
public void Should_Set_Description_On_Class()
90+
{
91+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
92+
93+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
94+
specProperties.Description.Should().NotBe("");
95+
}
96+
97+
[Fact]
98+
public void Should_Set_Description()
99+
{
100+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
101+
102+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
103+
var field = specProperties.Properties["description"];
104+
105+
field.Description.Should().NotBe("");
106+
}
107+
108+
[Fact]
109+
public void Should_Set_ExternalDocs()
110+
{
111+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
112+
113+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
114+
var field = specProperties.Properties["externalDocs"];
115+
116+
field.ExternalDocs.Url.Should().NotBe("");
117+
}
118+
119+
[Fact]
120+
public void Should_Set_ExternalDocs_Description()
121+
{
122+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
123+
124+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
125+
var field = specProperties.Properties["externalDocsWithDescription"];
126+
127+
field.ExternalDocs.Description.Should().NotBe("");
128+
}
129+
130+
[Fact]
131+
public void Should_Set_Item_Information()
132+
{
133+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
134+
135+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
136+
var field = specProperties.Properties["items"];
137+
138+
field.Type.Should().Be("array");
139+
(field.Items as V1JSONSchemaProps)?.Type?.Should().Be("string");
140+
field.MaxItems.Should().Be(42);
141+
field.MinItems.Should().Be(13);
142+
field.UniqueItems.Should().BeTrue();
143+
}
144+
145+
[Fact]
146+
public void Should_Set_Length_Information()
147+
{
148+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
149+
150+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
151+
var field = specProperties.Properties["length"];
152+
153+
field.MinLength.Should().Be(2);
154+
field.MaxLength.Should().Be(42);
155+
}
156+
157+
[Fact]
158+
public void Should_Set_MultipleOf()
159+
{
160+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
161+
162+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
163+
var field = specProperties.Properties["multipleOf"];
164+
165+
field.MultipleOf.Should().Be(15);
166+
}
167+
168+
[Fact]
169+
public void Should_Set_Pattern()
170+
{
171+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
172+
173+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
174+
var field = specProperties.Properties["pattern"];
175+
176+
field.Pattern.Should().Be(@"/\d*/");
177+
}
178+
179+
[Fact]
180+
public void Should_Set_RangeMinimum()
181+
{
182+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
183+
184+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
185+
var field = specProperties.Properties["rangeMinimum"];
186+
187+
field.Minimum.Should().Be(15);
188+
field.ExclusiveMinimum.Should().BeTrue();
189+
}
190+
191+
[Fact]
192+
public void Should_Set_RangeMaximum()
193+
{
194+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
195+
196+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
197+
var field = specProperties.Properties["rangeMaximum"];
198+
199+
field.Maximum.Should().Be(15);
200+
field.ExclusiveMaximum.Should().BeTrue();
201+
}
202+
203+
[Fact]
204+
public void Should_Set_Required()
205+
{
206+
var crd = EntityToCrdExtensions.CreateCrd(_testSpecEntity).Convert();
207+
208+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
209+
specProperties.Required.Should().Contain("required");
210+
}
211+
212+
[Fact]
213+
public void Should_Set_Required_Null_If_No_Required()
214+
{
215+
var crd = EntityToCrdExtensions.CreateCrd(_testStatusEntity).Convert();
216+
217+
var specProperties = crd.Spec.Validation.OpenAPIV3Schema.Properties["spec"];
218+
specProperties.Required.Should().BeNull();
219+
}
220+
}
221+
}

0 commit comments

Comments
 (0)