@kustodian/schema 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # @kustodian/schema
2
+
3
+ Zod schema definitions for validating Kustodian YAML configuration files. This package provides type-safe validation for Cluster, Template, Node, and NodeProfile resources.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @kustodian/schema
9
+ ```
10
+
11
+ ## API Overview
12
+
13
+ ### Resource Schemas
14
+
15
+ - **`cluster_schema`** - Cluster resource definition with Git/OCI source, templates, and node configuration
16
+ - **`template_schema`** - Template resource with kustomization definitions
17
+ - **`node_resource_schema`** - Node resource with role, address, SSH config, labels, and taints
18
+ - **`node_profile_resource_schema`** - Reusable node profile with labels, taints, and annotations
19
+
20
+ ### Validation Functions
21
+
22
+ ```typescript
23
+ import { validate_cluster, validate_template, validate_node_resource, validate_node_profile_resource } from '@kustodian/schema';
24
+
25
+ const result = validate_cluster(yamlData);
26
+ if (result.success) {
27
+ // result.data is fully typed as ClusterType
28
+ }
29
+ ```
30
+
31
+ ### Substitution Types
32
+
33
+ The package supports multiple substitution types for template values:
34
+
35
+ - **Generic** - Simple key-value substitutions
36
+ - **Version** - Container image version tracking with semver constraints
37
+ - **Namespace** - Kubernetes namespace with validation
38
+ - **1Password** - Secrets from 1Password vaults (`op://` references)
39
+ - **Doppler** - Secrets from Doppler projects
40
+
41
+ ### Type Guards
42
+
43
+ ```typescript
44
+ import { is_version_substitution, is_onepassword_substitution } from '@kustodian/schema';
45
+
46
+ if (is_version_substitution(sub)) {
47
+ // sub.registry is available
48
+ }
49
+ ```
50
+
51
+ ### Exported Types
52
+
53
+ All schemas export corresponding TypeScript types:
54
+
55
+ - `ClusterType`, `TemplateType`, `NodeResourceType`, `NodeProfileResourceType`
56
+ - `SubstitutionType`, `VersionSubstitutionType`, `GenericSubstitutionType`
57
+ - `KustomizationType`, `HealthCheckType`, `TaintSchemaType`
58
+
59
+ ## License
60
+
61
+ MIT
62
+
63
+ ## Repository
64
+
65
+ [github.com/lucasilverentand/kustodian](https://github.com/lucasilverentand/kustodian)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kustodian/schema",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "JSON Schema definitions for Kustodian YAML validation",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/index.ts CHANGED
@@ -3,3 +3,4 @@ export * from './cluster.js';
3
3
  export * from './common.js';
4
4
  export * from './node-list.js';
5
5
  export * from './profile.js';
6
+ export * from './sources.js';
package/src/sources.ts ADDED
@@ -0,0 +1,142 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * Git reference - exactly one of branch, tag, or commit must be specified.
5
+ */
6
+ export const git_ref_schema = z
7
+ .object({
8
+ branch: z.string().min(1).optional(),
9
+ tag: z.string().min(1).optional(),
10
+ commit: z.string().min(1).optional(),
11
+ })
12
+ .refine((data) => [data.branch, data.tag, data.commit].filter(Boolean).length === 1, {
13
+ message: "Exactly one of 'branch', 'tag', or 'commit' must be specified",
14
+ });
15
+
16
+ export type GitRefType = z.infer<typeof git_ref_schema>;
17
+
18
+ /**
19
+ * Git source configuration for fetching templates from a Git repository.
20
+ */
21
+ export const git_source_schema = z.object({
22
+ url: z.string().url(),
23
+ ref: git_ref_schema,
24
+ path: z.string().optional(),
25
+ });
26
+
27
+ export type GitSourceType = z.infer<typeof git_source_schema>;
28
+
29
+ /**
30
+ * HTTP archive source configuration for fetching templates from URLs.
31
+ * Supports tar.gz and zip archives.
32
+ */
33
+ export const http_source_schema = z.object({
34
+ url: z.string().url(),
35
+ checksum: z.string().optional(),
36
+ headers: z.record(z.string(), z.string()).optional(),
37
+ });
38
+
39
+ export type HttpSourceType = z.infer<typeof http_source_schema>;
40
+
41
+ /**
42
+ * OCI artifact source configuration for pulling templates from OCI registries.
43
+ */
44
+ export const oci_source_schema = z
45
+ .object({
46
+ registry: z.string().min(1),
47
+ repository: z.string().min(1),
48
+ tag: z.string().min(1).optional(),
49
+ digest: z.string().min(1).optional(),
50
+ })
51
+ .refine((data) => data.tag || data.digest, {
52
+ message: "Either 'tag' or 'digest' must be specified",
53
+ });
54
+
55
+ export type OciSourceType = z.infer<typeof oci_source_schema>;
56
+
57
+ /**
58
+ * Duration format for TTL values.
59
+ * Examples: 30m, 1h, 24h, 7d
60
+ */
61
+ export const duration_schema = z.string().regex(/^(\d+)(m|h|d)$/, {
62
+ message: "Duration must be in format: <number>(m|h|d), e.g., '30m', '1h', '7d'",
63
+ });
64
+
65
+ /**
66
+ * Template source configuration - union of all source types.
67
+ * Exactly one of git, http, or oci must be specified.
68
+ */
69
+ export const template_source_schema = z
70
+ .object({
71
+ name: z.string().min(1),
72
+ git: git_source_schema.optional(),
73
+ http: http_source_schema.optional(),
74
+ oci: oci_source_schema.optional(),
75
+ ttl: duration_schema.optional(),
76
+ })
77
+ .refine((data) => [data.git, data.http, data.oci].filter(Boolean).length === 1, {
78
+ message: "Exactly one of 'git', 'http', or 'oci' must be specified",
79
+ });
80
+
81
+ export type TemplateSourceType = z.infer<typeof template_source_schema>;
82
+
83
+ /**
84
+ * Type guard for Git sources.
85
+ */
86
+ export function is_git_source(
87
+ source: TemplateSourceType,
88
+ ): source is TemplateSourceType & { git: GitSourceType } {
89
+ return source.git !== undefined;
90
+ }
91
+
92
+ /**
93
+ * Type guard for HTTP sources.
94
+ */
95
+ export function is_http_source(
96
+ source: TemplateSourceType,
97
+ ): source is TemplateSourceType & { http: HttpSourceType } {
98
+ return source.http !== undefined;
99
+ }
100
+
101
+ /**
102
+ * Type guard for OCI sources.
103
+ */
104
+ export function is_oci_source(
105
+ source: TemplateSourceType,
106
+ ): source is TemplateSourceType & { oci: OciSourceType } {
107
+ return source.oci !== undefined;
108
+ }
109
+
110
+ /**
111
+ * Determines if a source reference is mutable (requires TTL-based refresh).
112
+ * - Git branches: mutable
113
+ * - Git tags/commits: immutable
114
+ * - HTTP with checksum: immutable
115
+ * - HTTP without checksum: mutable
116
+ * - OCI 'latest' tag: mutable
117
+ * - OCI other tags/digests: immutable
118
+ */
119
+ export function is_mutable_source(source: TemplateSourceType): boolean {
120
+ if (is_git_source(source)) {
121
+ return source.git.ref.branch !== undefined;
122
+ }
123
+
124
+ if (is_http_source(source)) {
125
+ return source.http.checksum === undefined;
126
+ }
127
+
128
+ if (is_oci_source(source)) {
129
+ return source.oci.tag === 'latest' && source.oci.digest === undefined;
130
+ }
131
+
132
+ return true;
133
+ }
134
+
135
+ /**
136
+ * Validates a template source object and returns the result.
137
+ */
138
+ export function validate_template_source(
139
+ data: unknown,
140
+ ): z.SafeParseReturnType<unknown, TemplateSourceType> {
141
+ return template_source_schema.safeParse(data);
142
+ }