sip/testutil/testutil.go
Sean Eagan 068afe5bb9 Remove Auth service from SIP
The auth service (Dex) does not depend on the SIP scheduling output
like the other services do, so it can be put in place independet
of SIP. This will remove complexity from SIP and give more
flexibility in how we deploy Dex through kustomize.

Change-Id: I1f871ae3be7d228cef867af6bed8ffffd6d0ea56
2021-04-27 14:03:40 -05:00

336 lines
10 KiB
Go

package testutil
import (
"fmt"
"github.com/onsi/gomega"
metal3 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
airshipv1 "sipcluster/pkg/api/v1"
)
var bmhRoleToLabelValue = map[airshipv1.BMHRole]string{
airshipv1.RoleControlPlane: "control-plane",
airshipv1.RoleWorker: "worker",
}
func UnscheduledSelector() labels.Selector {
sel := labels.NewSelector()
r, err := labels.NewRequirement(sipClusterLabel, selection.DoesNotExist, nil)
gomega.Expect(err).Should(gomega.Succeed())
return sel.Add(*r)
}
const (
// NOTE(aw442m): These constants have been redefined from the bmh package in order to avoid an import cycle.
sipClusterLabelName = "cluster"
sipClusterLabel = "sip.airshipit.org" + "/" + sipClusterLabelName
HostLabel = "vino.airshipit.org/host"
RackLabel = "vino.airshipit.org/rack"
bmhLabel = "example.org/bmh-label"
sshPrivateKeyBase64 = "DUMMY_DATA"
networkDataContent = `
{
"links": [
{
"id": "eno4",
"name": "eno4",
"type": "phy",
"mtu": 1500
},
{
"id": "enp59s0f1",
"name": "enp59s0f1",
"type": "phy",
"mtu": 9100
},
{
"id": "enp216s0f0",
"name": "enp216s0f0",
"type": "phy",
"mtu": 9100
},
{
"id": "bond0",
"name": "bond0",
"type": "bond",
"bond_links": [
"enp59s0f1",
"enp216s0f0"
],
"bond_mode": "802.3ad",
"bond_xmit_hash_policy": "layer3+4",
"bond_miimon": 100,
"mtu": 9100
},
{
"id": "bond0.41",
"name": "bond0.41",
"type": "vlan",
"vlan_link": "bond0",
"vlan_id": 41,
"mtu": 9100,
"vlan_mac_address": null
},
{
"id": "bond0.42",
"name": "bond0.42",
"type": "vlan",
"vlan_link": "bond0",
"vlan_id": 42,
"mtu": 9100,
"vlan_mac_address": null
},
{
"id": "bond0.44",
"name": "bond0.44",
"type": "vlan",
"vlan_link": "bond0",
"vlan_id": 44,
"mtu": 9100,
"vlan_mac_address": null
},
{
"id": "bond0.45",
"name": "bond0.45",
"type": "vlan",
"vlan_link": "bond0",
"vlan_id": 45,
"mtu": 9100,
"vlan_mac_address": null
}
],
"networks": [
{
"id": "oam-ipv6",
"type": "ipv6",
"link": "bond0.41",
"ip_address": "2001:1890:1001:293d::139",
"routes": [
{
"network": "::/0",
"netmask": "::/0",
"gateway": "2001:1890:1001:293d::1"
}
]
},
{
"id": "oam-ipv4",
"type": "ipv4",
"link": "bond0.41",
"ip_address": "32.68.51.139",
"netmask": "255.255.255.128",
"dns_nameservers": [
"135.188.34.124",
"135.38.244.16",
"135.188.34.84"
],
"routes": [
{
"network": "0.0.0.0",
"netmask": "0.0.0.0",
"gateway": "32.68.51.129"
}
]
},
{
"id": "pxe-ipv6",
"link": "eno4",
"type": "ipv6",
"ip_address": "fd00:900:100:138::11"
},
{
"id": "pxe-ipv4",
"link": "eno4",
"type": "ipv4",
"ip_address": "172.30.0.11",
"netmask": "255.255.255.128"
},
{
"id": "storage-ipv6",
"link": "bond0.42",
"type": "ipv6",
"ip_address": "fd00:900:100:139::15"
},
{
"id": "storage-ipv4",
"link": "bond0.42",
"type": "ipv4",
"ip_address": "172.31.1.15",
"netmask": "255.255.255.128"
},
{
"id": "ksn-ipv6",
"link": "bond0.44",
"type": "ipv6",
"ip_address": "fd00:900:100:13a::11"
},
{
"id": "ksn-ipv4",
"link": "bond0.44",
"type": "ipv4",
"ip_address": "172.29.0.11",
"netmask": "255.255.255.128"
}
]
}`
)
// CreateBMH initializes a BaremetalHost with specific parameters for use in test cases.
func CreateBMH(node int, namespace string, role airshipv1.BMHRole, rack int) (*metal3.BareMetalHost, *corev1.Secret) {
rackLabelValue := fmt.Sprintf("r%d", rack)
hostLabelValue := fmt.Sprintf("stl2%so%d", rackLabelValue, node)
networkDataName := fmt.Sprintf("node%d-network-data", node)
return &metal3.BareMetalHost{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("node0%d", node),
Namespace: namespace,
Labels: map[string]string{
bmhLabel: bmhRoleToLabelValue[role],
RackLabel: rackLabelValue,
HostLabel: hostLabelValue,
},
},
Spec: metal3.BareMetalHostSpec{
NetworkData: &corev1.SecretReference{
Namespace: namespace,
Name: networkDataName,
},
BMC: metal3.BMCDetails{
Address: "redfish+https://32.68.51.12/redfish/v1/Systems/System.Embedded.1",
},
},
}, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: networkDataName,
Namespace: namespace,
},
Data: map[string][]byte{
"networkData": []byte(networkDataContent),
},
Type: corev1.SecretTypeOpaque,
}
}
// CreateSIPCluster initializes a SIPCluster with specific parameters for use in test cases.
func CreateSIPCluster(name string, namespace string, controlPlanes int, workers int) (
*airshipv1.SIPCluster, *corev1.Secret) {
sshPrivateKeySecretName := fmt.Sprintf("%s-ssh-private-key", name)
return &airshipv1.SIPCluster{
TypeMeta: metav1.TypeMeta{
Kind: "SIPCluster",
APIVersion: "airship.airshipit.org/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: airshipv1.SIPClusterSpec{
Nodes: map[airshipv1.BMHRole]airshipv1.NodeSet{
airshipv1.RoleControlPlane: {
LabelSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
bmhLabel: bmhRoleToLabelValue[airshipv1.RoleControlPlane],
},
},
TopologyKey: HostLabel,
Count: &airshipv1.NodeCount{
Active: controlPlanes,
Standby: 0,
},
},
airshipv1.RoleWorker: {
LabelSelector: metav1.LabelSelector{
MatchLabels: map[string]string{
bmhLabel: bmhRoleToLabelValue[airshipv1.RoleWorker],
},
},
TopologyKey: HostLabel,
Count: &airshipv1.NodeCount{
Active: workers,
Standby: 0,
},
},
},
Services: airshipv1.SIPClusterServices{
JumpHost: []airshipv1.JumpHostService{
{
SIPClusterService: airshipv1.SIPClusterService{
Image: "quay.io/airshipit/jump-host",
NodePort: 30000,
NodeInterface: "eno3",
},
SSHAuthorizedKeys: []string{
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCyaozS8kZRw2a1d0O4YXhxtJlDPThqIZilGCsXLbukIFOyMUmMTwQAtwWp5epwU1+5ponC2uBENB6xCCj3cl5Rd43d2/B6HxyAPQGKo6/zKYGAKW2nzYDxSWMl6NUSsiJAyXUA7ZlNZQe0m8PmaferlkQyLLZo3NJpizz6U6ZCtxvj43vEl7NYWnLUEIzGP9zMqltIGnD4vYrU9keVKKXSsp+DkApnbrDapeigeGATCammy2xRrUQDuOvGHsfnQbXr2j0onpTIh0PiLrXLQAPDg8UJRgVB+ThX+neI3rQ320djzRABckNeE6e4Kkwzn+QdZsmA2SDvM9IU7boK1jVQlgUPp7zF5q3hbb8Rx7AadyTarBayUkCgNlrMqth+tmTMWttMqCPxJRGnhhvesAHIl55a28Kzz/2Oqa3J9zwzbyDIwlEXho0eAq3YXEPeBhl34k+7gOt/5Zdbh+yacFoxDh0LrshQgboAijcVVaXPeN0LsHEiVvYIzugwIvCkoFMPWoPj/kEGzPY6FCkVneDA7VoLTCoG8dlrN08Lf05/BGC7Wllm66pTNZC/cKXP+cjpQn1iEuiuPxnPldlMHx9sx2y/BRoft6oT/GzqkNy1NTY/xI+MfmxXnF5kwSbcTbzZQ9fZ8xjh/vmpPBgDNrxOEAT4N6OG7GQIhb9HEhXQCQ== example-key", //nolint
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwpOyZjZ4gB0OTvmofH3llh6cBCWaEiEmHZWSkDXr8Bih6HcXVOtYMcFi/ZnUVGUBPw3ATNQBZUaVCYKeF+nDfKTJ9hmnlsyHxV2LeMsVg1o15Pb6f+QJuavEqtE6HI7mHyId4Z1quVTJXDWDW8OZEG7M3VktauqAn/e9UJvlL0bGmTFD1XkNcbRsWMRWkQgt2ozqlgrpPtvrg2/+bNucxX++VUjnsn+fGgAT07kbnrZwppGnAfjbYthxhv7GeSD0+Z0Lf1kiKy/bhUqXsZIuexOfF0YrRyUH1KBl8GCX2OLBYvXHyusByqsrOPiROqRdjX5PsK6HSAS0lk0niTt1p example-key-2", // nolint
},
NodeSSHPrivateKeys: sshPrivateKeySecretName,
},
},
LoadBalancerControlPlane: []airshipv1.LoadBalancerServiceControlPlane{
{
SIPClusterService: airshipv1.SIPClusterService{
NodeInterface: "eno3",
NodePort: 30001,
},
},
},
LoadBalancerWorker: []airshipv1.LoadBalancerServiceWorker{
{
SIPClusterService: airshipv1.SIPClusterService{
NodeInterface: "eno3",
NodePort: 30002,
},
},
},
},
},
Status: airshipv1.SIPClusterStatus{},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: sshPrivateKeySecretName,
Namespace: namespace,
},
Data: map[string][]byte{
"key": []byte(sshPrivateKeyBase64),
},
Type: corev1.SecretTypeOpaque,
}
}
// CreateBMCAuthSecret creates a K8s Secret that matches the Metal3.io BaremetalHost credential format for use in test
// cases.
func CreateBMCAuthSecret(nodeName string, namespace string, username string, password string) *corev1.Secret {
return &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: corev1.SchemeGroupVersion.String(),
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-bmc-credentials", nodeName),
Namespace: namespace,
},
Data: map[string][]byte{
"username": []byte(username),
"password": []byte(password),
},
}
}
func CompareLabels(expected labels.Selector, actual map[string]string) error {
if !expected.Matches(labels.Set(actual)) {
return fmt.Errorf("labels do not match expected selector %v. Has labels %v", expected, actual)
}
return nil
}