Skip to content

Commit

Permalink
refactor: add CRD with kustomize CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
Christoph Bühler committed Sep 26, 2023
1 parent d77e110 commit ba5dda3
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 25 deletions.
1 change: 1 addition & 0 deletions src/KubeOps.Abstractions/KubeOps.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@




</Project>
50 changes: 50 additions & 0 deletions src/KubeOps.Abstractions/Kustomize/KustomizationConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using k8s;

namespace KubeOps.Abstractions.Kustomize;

/// <summary>
/// (Partial) definition for a kustomization yaml.
/// </summary>
public class KustomizationConfig : KubernetesObject
{
public KustomizationConfig()
{
ApiVersion = "kustomize.config.k8s.io/v1beta1";
Kind = "Kustomization";
}

/// <summary>
/// Namespace that should be set.
/// </summary>
public string? Namespace { get; set; }

/// <summary>
/// Name prefix that should be set.
/// </summary>
public string? NamePrefix { get; set; }

/// <summary>
/// Common labels for the resources.
/// </summary>
public IDictionary<string, string>? CommonLabels { get; set; }

/// <summary>
/// Resource list.
/// </summary>
public IList<string>? Resources { get; set; }

/// <summary>
/// List of merge patches.
/// </summary>
public IList<string>? PatchesStrategicMerge { get; set; }

/// <summary>
/// List of <see cref="KustomizationImage"/>.
/// </summary>
public IList<KustomizationImage>? Images { get; set; }

/// <summary>
/// List of <see cref="KustomizationConfigMapGenerator"/>.
/// </summary>
public IList<KustomizationConfigMapGenerator>? ConfigMapGenerator { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace KubeOps.Abstractions.Kustomize;

/// <summary>
/// Entitiy for config map generators in a kustomization.yaml file.
/// </summary>
public class KustomizationConfigMapGenerator
{
/// <summary>
/// The name of the config map.
/// </summary>
public string Name { get; set; } = string.Empty;

/// <summary>
/// List of files that should be added to the generated config map.
/// </summary>
public IList<string>? Files { get; set; }

/// <summary>
/// Config literals to add to the config map in the form of:
/// - NAME=value.
/// </summary>
public IList<string>? Literals { get; set; }
}
22 changes: 22 additions & 0 deletions src/KubeOps.Abstractions/Kustomize/KustomizationImage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace KubeOps.Abstractions.Kustomize;

/// <summary>
/// Definition for an "image" in a kustomization yaml.
/// </summary>
public class KustomizationImage
{
/// <summary>
/// Name of the image.
/// </summary>
public string Name { get; set; } = string.Empty;

/// <summary>
/// New name of the image.
/// </summary>
public string NewName { get; set; } = string.Empty;

/// <summary>
/// New tag of the image.
/// </summary>
public string NewTag { get; set; } = string.Empty;
}
15 changes: 13 additions & 2 deletions src/KubeOps.Cli/Commands/Generator/CrdGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using KubeOps.Cli.Output;
using KubeOps.Abstractions.Kustomize;
using KubeOps.Cli.Output;
using KubeOps.Cli.SyntaxObjects;

using McMaster.Extensions.CommandLineUtils;
Expand Down Expand Up @@ -53,11 +54,21 @@ public async Task<int> OnExecuteAsync()
_output.WriteLine($"Generate CRDs from project: {projectFile}.");

var parser = new ProjectParser(projectFile);
foreach (var crd in Transpiler.Crds.Transpile(await parser.Entities().ToListAsync()))
var crds = Transpiler.Crds.Transpile(await parser.Entities().ToListAsync()).ToList();
foreach (var crd in crds)
{
_result.Add($"{crd.Metadata.Name.Replace('.', '_')}.{Format.ToString().ToLowerInvariant()}", crd);
}

_result.Add(
$"kustomization.{Format.ToString().ToLowerInvariant()}",
new KustomizationConfig
{
Resources = crds
.ConvertAll(crd => $"{crd.Metadata.Name.Replace('.', '_')}.{Format.ToString().ToLower()}"),
CommonLabels = new Dictionary<string, string> { { "operator-element", "crd" } },
});

if (OutputPath is not null)
{
await _result.Write(OutputPath);
Expand Down
16 changes: 8 additions & 8 deletions src/KubeOps.Transpiler/Crds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ public static V1CustomResourceDefinition Transpile(Type type)
Plural = meta.PluralName,
ShortNames = type.GetCustomAttributes<KubernetesEntityShortNamesAttribute>(true)
.SelectMany(a => a.ShortNames).ToList() switch
{
{ Count: > 0 } p => p,
_ => null,
},
{
{ Count: > 0 } p => p,
_ => null,
},
};
crd.Spec.Scope = scope;

Expand Down Expand Up @@ -453,10 +453,10 @@ public static string PropertyName(PropertyInfo prop)
.Where(p => p.GetCustomAttribute<IgnoreAttribute>() == null)
.Select(PropertyName)
.ToList() switch
{
{ Count: > 0 } p => p,
_ => null,
},
{
{ Count: > 0 } p => p,
_ => null,
},
}
: null;

Expand Down
26 changes: 13 additions & 13 deletions src/KubeOps.Transpiler/Entities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ public static class Entities
public static (EntityMetadata Metadata, string Scope) ToEntityMetadata(Type entityType)
=> (entityType.GetCustomAttribute<KubernetesEntityAttribute>(),
entityType.GetCustomAttribute<EntityScopeAttribute>()) switch
{
(null, _) => throw new ArgumentException("The given type is not a valid Kubernetes entity."),
({ } attr, var scope) => (new(
Defaulted(attr.Kind, entityType.Name),
Defaulted(attr.ApiVersion, "v1"),
attr.Group,
attr.PluralName),
scope switch
{
null => Enum.GetName(typeof(EntityScope), EntityScope.Namespaced) ?? "namespaced",
_ => Enum.GetName(typeof(EntityScope), scope.Scope) ?? "namespaced",
}),
};
{
(null, _) => throw new ArgumentException("The given type is not a valid Kubernetes entity."),
({ } attr, var scope) => (new(
Defaulted(attr.Kind, entityType.Name),
Defaulted(attr.ApiVersion, "v1"),
attr.Group,
attr.PluralName),
scope switch
{
null => Enum.GetName(typeof(EntityScope), EntityScope.Namespaced) ?? "namespaced",
_ => Enum.GetName(typeof(EntityScope), scope.Scope) ?? "namespaced",
}),
};

private static string Defaulted(string value, string defaultValue) =>
string.IsNullOrWhiteSpace(value) ? defaultValue : value;
Expand Down
2 changes: 1 addition & 1 deletion test/KubeOps.Transpiler.Test/Rbac.Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void Should_Group_Same_Types_Together()
rule => rule.Resources.Contains("rbactest2s"));
roles.Should().HaveCount(2);
}

[Fact]
public void Should_Group_Types_With_Same_Verbs_Together()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public enum TestSpecEnum
[KubernetesEntity(Group = "kubeops.test.dev", ApiVersion = "V1")]
[GenericAdditionalPrinterColumn(".metadata.namespace", "Namespace", "string")]
[GenericAdditionalPrinterColumn(".metadata.creationTimestamp", "Age", "date")]
public class TestSpecEntity : IKubernetesObject<V1ObjectMeta>, ISpec<TestSpecEntitySpec>
public class TestSpecEntity : IKubernetesObject<V1ObjectMeta>, ISpec<TestSpecEntitySpec>
{
public string ApiVersion { get; set; } = "kubeops.test.dev/v1";
public string Kind { get; set; } = "TestSpecEntity";
Expand Down

0 comments on commit ba5dda3

Please sign in to comment.