sip/pkg/services/services_test.go
Sean Eagan 0db9ec08ba Add jumphost configuration to ssh to VMs
This adds a field to the SIP CRD to reference a Secret containing
SSH private keys to inject into the jump host container to be
used to SSH into the cluster's nodes. These should correspond
to whatever SSH authorized keys that will be included in the nodes.

These keys are then added to the jumphost container, and an SSH
config file is added to the ubuntu user's SSH config which includes
these keys along with host entries for each VM, which allows
them to be consumed by bash completion, which this also adds to
the jumphost image.

Signed-off-by: Sean Eagan <seaneagan1@gmail.com>
Change-Id: If2e948f567a867d8ee11353d79f3224faeac9215
2021-03-11 14:00:08 -06:00

224 lines
5.9 KiB
Go

package services_test
import (
"context"
"encoding/json"
airshipv1 "sipcluster/pkg/api/v1"
metal3 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sipcluster/pkg/services"
"sipcluster/pkg/vbmh"
"sipcluster/testutil"
)
const (
ip1 = "192.168.0.1"
ip2 = "192.168.0.2"
)
var bmh1 *metal3.BareMetalHost
var bmh2 *metal3.BareMetalHost
var m1 *vbmh.Machine
var m2 *vbmh.Machine
// Re-declared from services package for testing purposes
type host struct {
Name string `json:"name"`
BMC bmc `json:"bmc"`
}
type bmc struct {
IP string `json:"ip"`
Username string `json:"username"`
Password string `json:"password"`
}
var _ = Describe("Service Set", func() {
var machineList *vbmh.MachineList
BeforeEach(func() {
bmh1, _ = testutil.CreateBMH(1, "default", "control-plane", 1)
bmh2, _ = testutil.CreateBMH(2, "default", "control-plane", 2)
bmcUsername := "root"
bmcPassword := "password"
bmcSecret := testutil.CreateBMCAuthSecret(bmh1.GetName(), bmh1.GetNamespace(), bmcUsername,
bmcPassword)
Expect(k8sClient.Create(context.Background(), bmcSecret)).Should(Succeed())
bmh1.Spec.BMC.CredentialsName = bmcSecret.Name
bmh2.Spec.BMC.CredentialsName = bmcSecret.Name
m1 = &vbmh.Machine{
BMH: *bmh1,
Data: &vbmh.MachineData{
IPOnInterface: map[string]string{
"eno3": ip1,
},
},
}
m2 = &vbmh.Machine{
BMH: *bmh2,
Data: &vbmh.MachineData{
IPOnInterface: map[string]string{
"eno3": ip2,
},
},
}
machineList = &vbmh.MachineList{
Machines: map[string]*vbmh.Machine{
bmh1.GetName(): m1,
bmh2.GetName(): m2,
},
}
})
AfterEach(func() {
opts := []client.DeleteAllOfOption{client.InNamespace("default")}
Expect(k8sClient.DeleteAllOf(context.Background(), &metal3.BareMetalHost{}, opts...)).Should(Succeed())
Expect(k8sClient.DeleteAllOf(context.Background(), &airshipv1.SIPCluster{}, opts...)).Should(Succeed())
Expect(k8sClient.DeleteAllOf(context.Background(), &corev1.Secret{}, opts...)).Should(Succeed())
})
Context("When new SIP cluster is created", func() {
It("Deploys services", func() {
By("Getting machine IPs and creating secrets, pods, and nodeport service")
sipCluster, nodeSSHPrivateKeys := testutil.CreateSIPCluster("default", "default", 1, 1)
Expect(k8sClient.Create(context.Background(), nodeSSHPrivateKeys)).Should(Succeed())
machineList = &vbmh.MachineList{
Machines: map[string]*vbmh.Machine{
bmh1.GetName(): m1,
bmh2.GetName(): m2,
},
}
set := services.NewServiceSet(logger, *sipCluster, machineList, k8sClient)
serviceList, err := set.ServiceList()
Expect(serviceList).To(HaveLen(2))
Expect(err).To(Succeed())
for _, svc := range serviceList {
err := svc.Deploy()
Expect(err).ToNot(HaveOccurred())
}
Eventually(func() error {
return testDeployment(sipCluster, *machineList)
}, 5, 1).Should(Succeed())
})
It("Does not deploy a Jump Host when an invalid SSH key is provided", func() {
sip, _ := testutil.CreateSIPCluster("default", "default", 1, 1)
sip.Spec.Services.Auth = []airshipv1.SIPClusterService{}
sip.Spec.Services.LoadBalancer = []airshipv1.SIPClusterService{}
sip.Spec.Services.JumpHost[0].SSHAuthorizedKeys = []string{
"sshrsaAAAAAAAAAAAAAAAAAAAAAinvalidkey",
}
set := services.NewServiceSet(logger, *sip, machineList, k8sClient)
serviceList, err := set.ServiceList()
Expect(err).To(Succeed())
for _, svc := range serviceList {
err := svc.Deploy()
Expect(err).To(HaveOccurred())
}
})
})
})
func testDeployment(sip *airshipv1.SIPCluster, machineList vbmh.MachineList) error {
loadBalancerDeployment := &appsv1.Deployment{}
err := k8sClient.Get(context.Background(), types.NamespacedName{
Namespace: "default",
Name: services.LoadBalancerServiceName + "-" + sip.GetName(),
}, loadBalancerDeployment)
if err != nil {
return err
}
loadBalancerSecret := &corev1.Secret{}
err = k8sClient.Get(context.Background(), types.NamespacedName{
Namespace: "default",
Name: services.LoadBalancerServiceName + "-" + sip.GetName(),
}, loadBalancerSecret)
if err != nil {
return err
}
loadBalancerService := &corev1.Service{}
err = k8sClient.Get(context.Background(), types.NamespacedName{
Namespace: "default",
Name: services.LoadBalancerServiceName + "-" + sip.GetName(),
}, loadBalancerService)
if err != nil {
return err
}
jumpHostDeployment := &appsv1.Deployment{}
err = k8sClient.Get(context.Background(), types.NamespacedName{
Namespace: "default",
Name: services.JumpHostServiceName + "-" + sip.GetName(),
}, jumpHostDeployment)
if err != nil {
return err
}
jumpHostHostAliases := jumpHostDeployment.Spec.Template.Spec.HostAliases
Expect(jumpHostHostAliases).To(ConsistOf(
corev1.HostAlias{
IP: ip1,
Hostnames: []string{bmh1.GetName()},
},
corev1.HostAlias{
IP: ip2,
Hostnames: []string{bmh2.GetName()},
},
))
jumpHostService := &corev1.Service{}
err = k8sClient.Get(context.Background(), types.NamespacedName{
Namespace: "default",
Name: services.JumpHostServiceName + "-" + sip.GetName(),
}, jumpHostService)
if err != nil {
return err
}
jumpHostSecret := &corev1.Secret{}
err = k8sClient.Get(context.Background(), types.NamespacedName{
Namespace: "default",
Name: services.JumpHostServiceName + "-" + sip.GetName(),
}, jumpHostSecret)
if err != nil {
return err
}
var hosts []host
err = json.Unmarshal(jumpHostSecret.Data["hosts"], &hosts)
Expect(err).To(BeNil())
for _, host := range hosts {
for _, machine := range machineList.Machines {
if host.Name == machine.BMH.Name {
Expect(host.BMC.Username).To(Equal(machine.Data.BMCUsername))
Expect(host.BMC.Password).To(Equal(machine.Data.BMCPassword))
}
}
}
return nil
}