Skip to content

Commit ce20607

Browse files
authored
feat: remove pattern validations for [int | str] types (#75)
Signed-off-by: peefy <[email protected]>
1 parent 7a470ba commit ce20607

File tree

9 files changed

+509
-12
lines changed

9 files changed

+509
-12
lines changed

pkg/kube_resource/generator/generator.go

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
package generator
1616

1717
import (
18-
"bytes"
1918
"encoding/json"
2019
"errors"
2120
"fmt"
2221
"os"
2322
"path/filepath"
23+
"regexp"
24+
"strings"
2425

2526
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
2627
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install"
@@ -105,10 +106,13 @@ func GetSpecs(opts *GenOpts) ([]string, error) {
105106
if err != nil {
106107
return result, fmt.Errorf("could not load spec: %s, err: %s", opts.Spec, err)
107108
}
108-
contents := separateSubDocuments(crdContent)
109+
contents, err := splitDocuments(string(crdContent))
110+
if err != nil {
111+
return result, fmt.Errorf("could not load spec: %s, err: %s", opts.Spec, err)
112+
}
109113
for _, content := range contents {
110114
// generate openapi spec from crd
111-
swagger, err := generate(string(content))
115+
swagger, err := generate(content)
112116
if err != nil {
113117
return result, fmt.Errorf("could not generate swagger spec: %s, err: %s", opts.Spec, err)
114118
}
@@ -135,12 +139,33 @@ func GetSpecs(opts *GenOpts) ([]string, error) {
135139
return result, nil
136140
}
137141

138-
func separateSubDocuments(data []byte) [][]byte {
139-
lineBreak := "\n"
140-
if bytes.Contains(data, []byte("\r\n---\r\n")) {
141-
lineBreak = "\r\n"
142+
// splitDocuments returns a slice of all documents contained in a YAML string. Multiple documents can be divided by the
143+
// YAML document separator (---). It allows for white space and comments to be after the separator on the same line,
144+
// but will return an error if anything else is on the line.
145+
func splitDocuments(s string) ([]string, error) {
146+
docs := make([]string, 0)
147+
if len(s) > 0 {
148+
// The YAML document separator is any line that starts with ---
149+
yamlSeparatorRegexp := regexp.MustCompile(`\n---.*\n`)
150+
151+
// Find all separators, check them for invalid content, and append each document to docs
152+
separatorLocations := yamlSeparatorRegexp.FindAllStringIndex(s, -1)
153+
prev := 0
154+
for i := range separatorLocations {
155+
loc := separatorLocations[i]
156+
separator := s[loc[0]:loc[1]]
157+
// If the next non-whitespace character on the line following the separator is not a comment, return an error
158+
trimmedContentAfterSeparator := strings.TrimSpace(separator[4:])
159+
if len(trimmedContentAfterSeparator) > 0 && trimmedContentAfterSeparator[0] != '#' {
160+
return nil, fmt.Errorf("invalid document separator: %s", strings.TrimSpace(separator))
161+
}
162+
163+
docs = append(docs, s[prev:loc[0]])
164+
prev = loc[1]
165+
}
166+
docs = append(docs, s[prev:])
142167
}
143-
return bytes.Split(data, []byte(lineBreak+"---"+lineBreak))
168+
return docs, nil
144169
}
145170

146171
// generate swagger model based on crd

pkg/kube_resource/generator/generator_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,10 +623,10 @@ func TestGenerate(t *testing.T) {
623623
fmt.Println(string(data))
624624
}
625625

626-
func TestSeparateSubDocuments(t *testing.T) {
626+
func TestSplitDocuments(t *testing.T) {
627627
crds := v1Crd + v1beta1Crd
628-
files := separateSubDocuments([]byte(crds))
628+
files, _ := splitDocuments(crds)
629629
if len(files) != 3 {
630-
t.Errorf("separateSubDocuments failed. expected 3, got %d", len(files))
630+
t.Errorf("splitDocuments failed. expected 3, got %d", len(files))
631631
}
632632
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
"""
2+
This file was generated by the KCL auto-gen tool. DO NOT EDIT.
3+
Editing this file might prove futile when you re-run the KCL auto-gen generate command.
4+
"""
5+
import k8s.apimachinery.pkg.apis.meta.v1
6+
7+
8+
schema GlobalNetworkPolicy:
9+
"""
10+
crd projectcalico org v1 global network policy
11+
12+
Attributes
13+
----------
14+
action : str, default is Undefined, optional
15+
action
16+
apiVersion : str, default is "crd.projectcalico.org/v1", required
17+
APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
18+
kind : str, default is "GlobalNetworkPolicy", required
19+
Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
20+
destination : CrdProjectcalicoOrgV1GlobalNetworkPolicyDestination, default is Undefined, optional
21+
destination
22+
metadata : v1.ObjectMeta, default is Undefined, optional
23+
metadata
24+
"""
25+
26+
27+
action?: str
28+
29+
apiVersion: "crd.projectcalico.org/v1" = "crd.projectcalico.org/v1"
30+
31+
kind: "GlobalNetworkPolicy" = "GlobalNetworkPolicy"
32+
33+
destination?: CrdProjectcalicoOrgV1GlobalNetworkPolicyDestination
34+
35+
metadata?: v1.ObjectMeta
36+
37+
38+
schema CrdProjectcalicoOrgV1GlobalNetworkPolicyDestination:
39+
"""
40+
Destination contains the match criteria that apply to destination entity.
41+
42+
Attributes
43+
----------
44+
namespaceSelector : str, default is Undefined, optional
45+
NamespaceSelector is an optional field that contains a selector expression. Only traffic that originates from (or terminates at) endpoints within the selected namespaces will be matched. When both NamespaceSelector and another selector are defined on the same rule, then only workload endpoints that are matched by both selectors will be selected by the rule.
46+
For NetworkPolicy, an empty NamespaceSelector implies that the Selector is limited to selecting only workload endpoints in the same namespace as the NetworkPolicy.
47+
For NetworkPolicy, `global()` NamespaceSelector implies that the Selector is limited to selecting only GlobalNetworkSet or HostEndpoint.
48+
For GlobalNetworkPolicy, an empty NamespaceSelector implies the Selector applies to workload endpoints across all namespaces.
49+
nets : [str], default is Undefined, optional
50+
Nets is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) IP addresses in any of the given subnets.
51+
notNets : [str], default is Undefined, optional
52+
NotNets is the negated version of the Nets field.
53+
notPorts : [int | str], default is Undefined, optional
54+
NotPorts is the negated version of the Ports field. Since only some protocols have ports, if any ports are specified it requires the Protocol match in the Rule to be set to "TCP" or "UDP".
55+
notSelector : str, default is Undefined, optional
56+
NotSelector is the negated version of the Selector field. See Selector field for subtleties with negated selectors.
57+
ports : [int | str], default is Undefined, optional
58+
Ports is an optional field that restricts the rule to only apply to traffic that has a source (destination) port that matches one of these ranges/values. This value is a list of integers or strings that represent ranges of ports.
59+
Since only some protocols have ports, if any ports are specified it requires the Protocol match in the Rule to be set to "TCP" or "UDP".
60+
selector : str, default is Undefined, optional
61+
Selector is an optional field that contains a selector expression (see Policy for sample syntax). Only traffic that originates from (terminates at) endpoints matching the selector will be matched.
62+
Note that: in addition to the negated version of the Selector (see NotSelector below), the selector expression syntax itself supports negation. The two types of negation are subtly different. One negates the set of matched endpoints, the other negates the whole match:
63+
Selector = "!has(my_label)" matches packets that are from other Calico-controlled endpoints that do not have the label "my_label".
64+
NotSelector = "has(my_label)" matches packets that are not from Calico-controlled endpoints that do have the label "my_label".
65+
The effect is that the latter will accept packets from non-Calico sources whereas the former is limited to packets from Calico-controlled endpoints.
66+
serviceAccounts : CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServiceAccounts, default is Undefined, optional
67+
service accounts
68+
services : CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServices, default is Undefined, optional
69+
services
70+
"""
71+
72+
73+
namespaceSelector?: str
74+
75+
nets?: [str]
76+
77+
notNets?: [str]
78+
79+
notPorts?: [int | str]
80+
81+
notSelector?: str
82+
83+
ports?: [int | str]
84+
85+
selector?: str
86+
87+
serviceAccounts?: CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServiceAccounts
88+
89+
services?: CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServices
90+
91+
92+
schema CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServiceAccounts:
93+
"""
94+
ServiceAccounts is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) a pod running as a matching service account.
95+
96+
Attributes
97+
----------
98+
names : [str], default is Undefined, optional
99+
Names is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) a pod running as a service account whose name is in the list.
100+
selector : str, default is Undefined, optional
101+
Selector is an optional field that restricts the rule to only apply to traffic that originates from (or terminates at) a pod running as a service account that matches the given label selector. If both Names and Selector are specified then they are AND'ed.
102+
"""
103+
104+
105+
names?: [str]
106+
107+
selector?: str
108+
109+
110+
schema CrdProjectcalicoOrgV1GlobalNetworkPolicyDestinationServices:
111+
"""
112+
Services is an optional field that contains options for matching Kubernetes Services. If specified, only traffic that originates from or terminates at endpoints within the selected service(s) will be matched, and only to/from each endpoint's port.
113+
Services cannot be specified on the same rule as Selector, NotSelector, NamespaceSelector, Nets, NotNets or ServiceAccounts.
114+
Ports and NotPorts can only be specified with Services on ingress rules.
115+
116+
Attributes
117+
----------
118+
name : str, default is Undefined, optional
119+
Name specifies the name of a Kubernetes Service to match.
120+
namespace : str, default is Undefined, optional
121+
Namespace specifies the namespace of the given Service. If left empty, the rule will match within this policy's namespace.
122+
"""
123+
124+
125+
name?: str
126+
127+
namespace?: str
128+
129+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""
2+
This is the managed_fields_entry module in k8s.apimachinery.pkg.apis.meta.v1 package.
3+
This file was generated by the KCL auto-gen tool. DO NOT EDIT.
4+
Editing this file might prove futile when you re-run the KCL auto-gen generate command.
5+
"""
6+
7+
8+
schema ManagedFieldsEntry:
9+
"""
10+
ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource that the fieldset applies to.
11+
12+
Attributes
13+
----------
14+
apiVersion : str, default is Undefined, optional
15+
APIVersion defines the version of this resource that this field set applies to. The format is "group/version" just like the top-level APIVersion field. It is necessary to track the version of a field set because it cannot be automatically converted.
16+
fieldsType : str, default is Undefined, optional
17+
FieldsType is the discriminator for the different fields format and version. There is currently only one possible value: "FieldsV1"
18+
fieldsV1 : any, default is Undefined, optional
19+
FieldsV1 holds the first JSON version format as described in the "FieldsV1" type.
20+
manager : str, default is Undefined, optional
21+
Manager is an identifier of the workflow managing these fields.
22+
operation : str, default is Undefined, optional
23+
Operation is the type of operation which lead to this ManagedFieldsEntry being created. The only valid values for this field are 'Apply' and 'Update'.
24+
time : str, default is Undefined, optional
25+
Time is timestamp of when these fields were set. It should always be empty if Operation is 'Apply'
26+
"""
27+
28+
29+
apiVersion?: str
30+
31+
fieldsType?: str
32+
33+
fieldsV1?: any
34+
35+
manager?: str
36+
37+
operation?: str
38+
39+
time?: str
40+
41+

0 commit comments

Comments
 (0)