-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Switch default calico encapsulation to VXLAN, add annotations for aut…
…odetection (#514)
- Loading branch information
Showing
5 changed files
with
278 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package calico | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/canonical/k8s/pkg/k8sd/types" | ||
) | ||
|
||
const ( | ||
annotationAPIServerEnabled = "k8sd/v1alpha1/calico/apiserver-enabled" | ||
annotationEncapsulationV4 = "k8sd/v1alpha1/calico/encapsulation-v4" | ||
annotationEncapsulationV6 = "k8sd/v1alpha1/calico/encapsulation-v6" | ||
annotationAutodetectionV4FirstFound = "k8sd/v1alpha1/calico/autodetection-v4/firstFound" | ||
annotationAutodetectionV4Kubernetes = "k8sd/v1alpha1/calico/autodetection-v4/kubernetes" | ||
annotationAutodetectionV4Interface = "k8sd/v1alpha1/calico/autodetection-v4/interface" | ||
annotationAutodetectionV4SkipInterface = "k8sd/v1alpha1/calico/autodetection-v4/skipInterface" | ||
annotationAutodetectionV4CanReach = "k8sd/v1alpha1/calico/autodetection-v4/canReach" | ||
annotationAutodetectionV4CIDRs = "k8sd/v1alpha1/calico/autodetection-v4/cidrs" | ||
annotationAutodetectionV6FirstFound = "k8sd/v1alpha1/calico/autodetection-v6/firstFound" | ||
annotationAutodetectionV6Kubernetes = "k8sd/v1alpha1/calico/autodetection-v6/kubernetes" | ||
annotationAutodetectionV6Interface = "k8sd/v1alpha1/calico/autodetection-v6/interface" | ||
annotationAutodetectionV6SkipInterface = "k8sd/v1alpha1/calico/autodetection-v6/skipInterface" | ||
annotationAutodetectionV6CanReach = "k8sd/v1alpha1/calico/autodetection-v6/canReach" | ||
annotationAutodetectionV6CIDRs = "k8sd/v1alpha1/calico/autodetection-v6/cidrs" | ||
) | ||
|
||
type config struct { | ||
encapsulationV4 string | ||
encapsulationV6 string | ||
apiServerEnabled bool | ||
autodetectionV4 map[string]any | ||
autodetectionV6 map[string]any | ||
} | ||
|
||
func checkEncapsulation(v string) error { | ||
switch v { | ||
case "VXLAN", "IPIP", "IPIPCrossSubnet", "VXLANCrossSubnet", "None": | ||
return nil | ||
} | ||
return fmt.Errorf("unsupported encapsulation type: %s", v) | ||
} | ||
|
||
func parseAutodetectionAnnotations(annotations types.Annotations, autodetectionMap map[string]string) (map[string]any, error) { | ||
var autodetectionAnnotations []string | ||
var autodetectionKey string | ||
var autodetectionValue any | ||
|
||
for annotation, key := range autodetectionMap { | ||
if v, ok := annotations.Get(annotation); ok { | ||
autodetectionAnnotations = append(autodetectionAnnotations, annotation) | ||
autodetectionKey = key | ||
autodetectionValue = v | ||
} | ||
} | ||
|
||
if len(autodetectionAnnotations) > 1 { | ||
return nil, fmt.Errorf("multiple annotations found: %s", strings.Join(autodetectionAnnotations, ", ")) | ||
} | ||
|
||
// If any annotation is set, return the map otherwise it's left nil | ||
if autodetectionKey != "" { | ||
switch autodetectionKey { | ||
case "firstFound": | ||
autodetectionValue = autodetectionValue == "true" | ||
case "cidrs": | ||
autodetectionValue = strings.Split(autodetectionValue.(string), ",") | ||
} | ||
|
||
return map[string]any{ | ||
autodetectionKey: autodetectionValue, | ||
}, nil | ||
} | ||
|
||
return nil, nil | ||
} | ||
|
||
func internalConfig(annotations types.Annotations) (config, error) { | ||
c := config{ | ||
encapsulationV4: defaultEncapsulation, | ||
encapsulationV6: defaultEncapsulation, | ||
apiServerEnabled: defaultAPIServerEnabled, | ||
} | ||
|
||
if v, ok := annotations.Get(annotationAPIServerEnabled); ok { | ||
c.apiServerEnabled = v == "true" | ||
} | ||
|
||
if v, ok := annotations.Get(annotationEncapsulationV4); ok { | ||
if err := checkEncapsulation(v); err != nil { | ||
return config{}, fmt.Errorf("invalid encapsulation-v4 annotation: %w", err) | ||
} | ||
c.encapsulationV4 = v | ||
} | ||
|
||
if v, ok := annotations.Get(annotationEncapsulationV6); ok { | ||
if err := checkEncapsulation(v); err != nil { | ||
return config{}, fmt.Errorf("invalid encapsulation-v6 annotation: %w", err) | ||
} | ||
c.encapsulationV6 = v | ||
} | ||
|
||
v4Map := map[string]string{ | ||
annotationAutodetectionV4FirstFound: "firstFound", | ||
annotationAutodetectionV4Kubernetes: "kubernetes", | ||
annotationAutodetectionV4Interface: "interface", | ||
annotationAutodetectionV4SkipInterface: "skipInterface", | ||
annotationAutodetectionV4CanReach: "canReach", | ||
annotationAutodetectionV4CIDRs: "cidrs", | ||
} | ||
|
||
autodetectionV4, err := parseAutodetectionAnnotations(annotations, v4Map) | ||
if err != nil { | ||
return config{}, fmt.Errorf("error parsing autodetection-v4 annotations: %w", err) | ||
} | ||
|
||
if autodetectionV4 != nil { | ||
c.autodetectionV4 = autodetectionV4 | ||
} | ||
|
||
v6Map := map[string]string{ | ||
annotationAutodetectionV6FirstFound: "firstFound", | ||
annotationAutodetectionV6Kubernetes: "kubernetes", | ||
annotationAutodetectionV6Interface: "interface", | ||
annotationAutodetectionV6SkipInterface: "skipInterface", | ||
annotationAutodetectionV6CanReach: "canReach", | ||
annotationAutodetectionV6CIDRs: "cidrs", | ||
} | ||
|
||
autodetectionV6, err := parseAutodetectionAnnotations(annotations, v6Map) | ||
if err != nil { | ||
return config{}, fmt.Errorf("error parsing autodetection-v6 annotations: %w", err) | ||
} | ||
|
||
if autodetectionV6 != nil { | ||
c.autodetectionV6 = autodetectionV6 | ||
} | ||
|
||
return c, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package calico | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestInternalConfig(t *testing.T) { | ||
for _, tc := range []struct { | ||
name string | ||
annotations map[string]string | ||
expectedConfig config | ||
expectError bool | ||
}{ | ||
{ | ||
name: "Empty", | ||
annotations: map[string]string{}, | ||
expectedConfig: config{ | ||
apiServerEnabled: false, | ||
encapsulationV4: "VXLAN", | ||
encapsulationV6: "VXLAN", | ||
}, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "Valid", | ||
annotations: map[string]string{ | ||
annotationAPIServerEnabled: "true", | ||
annotationEncapsulationV4: "IPIP", | ||
}, | ||
expectedConfig: config{ | ||
apiServerEnabled: true, | ||
encapsulationV4: "IPIP", | ||
encapsulationV6: "VXLAN", | ||
}, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "InvalidEncapsulation", | ||
annotations: map[string]string{ | ||
annotationEncapsulationV4: "Invalid", | ||
}, | ||
expectError: true, | ||
}, | ||
{ | ||
name: "InvalidAPIServerEnabled", | ||
annotations: map[string]string{ | ||
annotationAPIServerEnabled: "invalid", | ||
annotationEncapsulationV4: "VXLAN", | ||
}, | ||
expectedConfig: config{ | ||
apiServerEnabled: false, | ||
encapsulationV4: "VXLAN", | ||
encapsulationV6: "VXLAN", | ||
}, | ||
expectError: false, | ||
}, | ||
{ | ||
name: "MultipleAutodetectionV4", | ||
annotations: map[string]string{ | ||
annotationAutodetectionV4FirstFound: "true", | ||
annotationAutodetectionV4Kubernetes: "true", | ||
}, | ||
expectError: true, | ||
}, | ||
{ | ||
name: "ValidAutodetectionCidrs", | ||
annotations: map[string]string{ | ||
annotationAutodetectionV4CIDRs: "10.1.0.0/16,2001:0db8::/32", | ||
}, | ||
expectedConfig: config{ | ||
apiServerEnabled: false, | ||
encapsulationV4: "VXLAN", | ||
encapsulationV6: "VXLAN", | ||
autodetectionV4: map[string]any{ | ||
"cidrs": []string{"10.1.0.0/16", "2001:0db8::/32"}, | ||
}, | ||
autodetectionV6: nil, | ||
}, | ||
expectError: false, | ||
}, | ||
} { | ||
t.Run(tc.name, func(t *testing.T) { | ||
g := NewWithT(t) | ||
annotations := make(map[string]string) | ||
for k, v := range tc.annotations { | ||
annotations[k] = v | ||
} | ||
|
||
parsed, err := internalConfig(annotations) | ||
if tc.expectError { | ||
g.Expect(err).To(HaveOccurred()) | ||
} else { | ||
g.Expect(err).ToNot(HaveOccurred()) | ||
g.Expect(parsed).To(Equal(tc.expectedConfig)) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters