Merge branch 'master' into aks-chart-rbac
This commit is contained in:
@@ -676,10 +676,8 @@ func (p *ACIProvider) getContainers(pod *v1.Pod) ([]aci.Container, error) {
|
|||||||
|
|
||||||
c.EnvironmentVariables = make([]aci.EnvironmentVariable, 0, len(container.Env))
|
c.EnvironmentVariables = make([]aci.EnvironmentVariable, 0, len(container.Env))
|
||||||
for _, e := range container.Env {
|
for _, e := range container.Env {
|
||||||
c.EnvironmentVariables = append(c.EnvironmentVariables, aci.EnvironmentVariable{
|
envVar := getACIEnvVar(e)
|
||||||
Name: e.Name,
|
c.EnvironmentVariables = append(c.EnvironmentVariables, envVar)
|
||||||
Value: e.Value,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(robbiezhang): ACI CPU request must be times of 10m
|
// NOTE(robbiezhang): ACI CPU request must be times of 10m
|
||||||
@@ -724,11 +722,67 @@ func (p *ACIProvider) getContainers(pod *v1.Pod) ([]aci.Container, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if container.LivenessProbe != nil {
|
||||||
|
probe, err := getProbe(container.LivenessProbe)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.LivenessProbe = probe
|
||||||
|
}
|
||||||
|
|
||||||
|
if container.ReadinessProbe != nil {
|
||||||
|
probe, err := getProbe(container.ReadinessProbe)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.ReadinessProbe = probe
|
||||||
|
}
|
||||||
|
|
||||||
containers = append(containers, c)
|
containers = append(containers, c)
|
||||||
}
|
}
|
||||||
return containers, nil
|
return containers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getProbe(probe *v1.Probe) (*aci.ContainerProbe, error) {
|
||||||
|
|
||||||
|
if probe.Handler.Exec != nil && probe.Handler.HTTPGet != nil {
|
||||||
|
return nil, fmt.Errorf("probe may not specify more than one of \"exec\" and \"httpGet\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if probe.Handler.Exec == nil && probe.Handler.HTTPGet == nil {
|
||||||
|
return nil, fmt.Errorf("probe must specify one of \"exec\" and \"httpGet\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probes have can have a Exec or HTTP Get Handler.
|
||||||
|
// Create those if they exist, then add to the
|
||||||
|
// ContainerProbe struct
|
||||||
|
var exec *aci.ContainerExecProbe
|
||||||
|
if probe.Handler.Exec != nil {
|
||||||
|
exec = &aci.ContainerExecProbe{
|
||||||
|
Command: probe.Handler.Exec.Command,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var httpGET *aci.ContainerHTTPGetProbe
|
||||||
|
if probe.Handler.HTTPGet != nil {
|
||||||
|
httpGET = &aci.ContainerHTTPGetProbe{
|
||||||
|
Port: probe.Handler.HTTPGet.Port.IntValue(),
|
||||||
|
Path: probe.Handler.HTTPGet.Path,
|
||||||
|
Scheme: string(probe.Handler.HTTPGet.Scheme),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &aci.ContainerProbe{
|
||||||
|
Exec: exec,
|
||||||
|
HTTPGet: httpGET,
|
||||||
|
InitialDelaySeconds: probe.InitialDelaySeconds,
|
||||||
|
Period: probe.PeriodSeconds,
|
||||||
|
FailureThreshold: probe.FailureThreshold,
|
||||||
|
SuccessThreshold: probe.SuccessThreshold,
|
||||||
|
TimeoutSeconds: probe.TimeoutSeconds,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *ACIProvider) getVolumes(pod *v1.Pod) ([]aci.Volume, error) {
|
func (p *ACIProvider) getVolumes(pod *v1.Pod) ([]aci.Volume, error) {
|
||||||
volumes := make([]aci.Volume, 0, len(pod.Spec.Volumes))
|
volumes := make([]aci.Volume, 0, len(pod.Spec.Volumes))
|
||||||
for _, v := range pod.Spec.Volumes {
|
for _, v := range pod.Spec.Volumes {
|
||||||
@@ -1058,3 +1112,20 @@ func filterServiceAccountSecretVolume(osType string, containerGroup *aci.Contain
|
|||||||
containerGroup.ContainerGroupProperties.Volumes = volumes
|
containerGroup.ContainerGroupProperties.Volumes = volumes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getACIEnvVar(e v1.EnvVar) aci.EnvironmentVariable {
|
||||||
|
var envVar aci.EnvironmentVariable
|
||||||
|
// If the variable is a secret, use SecureValue
|
||||||
|
if e.ValueFrom.SecretKeyRef != nil {
|
||||||
|
envVar = aci.EnvironmentVariable{
|
||||||
|
Name: e.Name,
|
||||||
|
SecureValue: e.Value,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
envVar = aci.EnvironmentVariable{
|
||||||
|
Name: e.Name,
|
||||||
|
Value: e.Value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return envVar
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -363,6 +364,58 @@ func TestGetPodWithoutResourceRequestsLimits(t *testing.T) {
|
|||||||
"Containers[0].Resources.Requests.Memory doesn't match")
|
"Containers[0].Resources.Requests.Memory doesn't match")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPodToACISecretEnvVar(t *testing.T) {
|
||||||
|
|
||||||
|
testKey := "testVar"
|
||||||
|
testVal := "testVal"
|
||||||
|
|
||||||
|
e := v1.EnvVar{
|
||||||
|
Name: testKey,
|
||||||
|
Value: testVal,
|
||||||
|
ValueFrom: &v1.EnvVarSource{
|
||||||
|
SecretKeyRef: &v1.SecretKeySelector{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
aciEnvVar := getACIEnvVar(e)
|
||||||
|
|
||||||
|
if aciEnvVar.Value != "" {
|
||||||
|
t.Fatalf("ACI Env Variable Value should be empty for a secret")
|
||||||
|
}
|
||||||
|
|
||||||
|
if aciEnvVar.Name != testKey {
|
||||||
|
t.Fatalf("ACI Env Variable Name does not match expected Name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if aciEnvVar.SecureValue != testVal {
|
||||||
|
t.Fatalf("ACI Env Variable Secure Value does not match expected value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPodToACIEnvVar(t *testing.T) {
|
||||||
|
|
||||||
|
testKey := "testVar"
|
||||||
|
testVal := "testVal"
|
||||||
|
|
||||||
|
e := v1.EnvVar{
|
||||||
|
Name: testKey,
|
||||||
|
Value: testVal,
|
||||||
|
ValueFrom: &v1.EnvVarSource{},
|
||||||
|
}
|
||||||
|
aciEnvVar := getACIEnvVar(e)
|
||||||
|
|
||||||
|
if aciEnvVar.SecureValue != "" {
|
||||||
|
t.Fatalf("ACI Env Variable Secure Value should be empty for non-secret variables")
|
||||||
|
}
|
||||||
|
|
||||||
|
if aciEnvVar.Name != testKey {
|
||||||
|
t.Fatalf("ACI Env Variable Name does not match expected Name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if aciEnvVar.Value != testVal {
|
||||||
|
t.Fatalf("ACI Env Variable Value does not match expected value")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func prepareMocks() (*AADMock, *ACIMock, *ACIProvider, error) {
|
func prepareMocks() (*AADMock, *ACIMock, *ACIProvider, error) {
|
||||||
aadServerMocker := NewAADMock()
|
aadServerMocker := NewAADMock()
|
||||||
aciServerMocker := NewACIMock()
|
aciServerMocker := NewACIMock()
|
||||||
@@ -408,3 +461,127 @@ func prepareMocks() (*AADMock, *ACIMock, *ACIProvider, error) {
|
|||||||
func ptrQuantity(q resource.Quantity) *resource.Quantity {
|
func ptrQuantity(q resource.Quantity) *resource.Quantity {
|
||||||
return &q
|
return &q
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreatePodWithLivenessProbe(t *testing.T) {
|
||||||
|
_, aciServerMocker, provider, err := prepareMocks()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to prepare the mocks", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
podName := "pod-" + uuid.New().String()
|
||||||
|
podNamespace := "ns-" + uuid.New().String()
|
||||||
|
|
||||||
|
aciServerMocker.OnCreate = func(subscription, resourceGroup, containerGroup string, cg *aci.ContainerGroup) (int, interface{}) {
|
||||||
|
assert.Equal(t, fakeSubscription, subscription, "Subscription doesn't match")
|
||||||
|
assert.Equal(t, fakeResourceGroup, resourceGroup, "Resource group doesn't match")
|
||||||
|
assert.NotNil(t, cg, "Container group is nil")
|
||||||
|
assert.Equal(t, podNamespace+"-"+podName, containerGroup, "Container group name is not expected")
|
||||||
|
assert.NotNil(t, cg.ContainerGroupProperties, "Container group properties should not be nil")
|
||||||
|
assert.NotNil(t, cg.ContainerGroupProperties.Containers, "Containers should not be nil")
|
||||||
|
assert.Equal(t, 1, len(cg.ContainerGroupProperties.Containers), "1 Container is expected")
|
||||||
|
assert.Equal(t, "nginx", cg.ContainerGroupProperties.Containers[0].Name, "Container nginx is expected")
|
||||||
|
assert.NotNil(t, cg.Containers[0].LivenessProbe, "Liveness probe expected")
|
||||||
|
assert.Equal(t, cg.Containers[0].LivenessProbe.InitialDelaySeconds, 10, "Initial Probe Delay doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].LivenessProbe.Period, 5, "Probe Period doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].LivenessProbe.TimeoutSeconds, 60, "Probe Timeout doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].LivenessProbe.SuccessThreshold, 3, "Probe Success Threshold doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].LivenessProbe.FailureThreshold, 5, "Probe Failure Threshold doesn't match")
|
||||||
|
assert.NotNil(t, cg.Containers[0].LivenessProbe.HTTPGet, "Expected an HTTP Get Probe")
|
||||||
|
|
||||||
|
pod := &v1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: podName,
|
||||||
|
Namespace: podNamespace,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{
|
||||||
|
v1.Container{
|
||||||
|
Name: "nginx",
|
||||||
|
LivenessProbe: &v1.Probe{
|
||||||
|
Handler: v1.Handler{
|
||||||
|
HTTPGet: &v1.HTTPGetAction{
|
||||||
|
Port: intstr.FromString("8080"),
|
||||||
|
Path: "/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
InitialDelaySeconds: 10,
|
||||||
|
PeriodSeconds: 5,
|
||||||
|
TimeoutSeconds: 60,
|
||||||
|
SuccessThreshold: 3,
|
||||||
|
FailureThreshold: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := provider.CreatePod(pod); err != nil {
|
||||||
|
t.Fatal("Failed to create pod", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.StatusOK, cg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreatePodWithReadinessProbe(t *testing.T) {
|
||||||
|
_, aciServerMocker, provider, err := prepareMocks()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Unable to prepare the mocks", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
podName := "pod-" + uuid.New().String()
|
||||||
|
podNamespace := "ns-" + uuid.New().String()
|
||||||
|
|
||||||
|
aciServerMocker.OnCreate = func(subscription, resourceGroup, containerGroup string, cg *aci.ContainerGroup) (int, interface{}) {
|
||||||
|
assert.Equal(t, fakeSubscription, subscription, "Subscription doesn't match")
|
||||||
|
assert.Equal(t, fakeResourceGroup, resourceGroup, "Resource group doesn't match")
|
||||||
|
assert.NotNil(t, cg, "Container group is nil")
|
||||||
|
assert.Equal(t, podNamespace+"-"+podName, containerGroup, "Container group name is not expected")
|
||||||
|
assert.NotNil(t, cg.ContainerGroupProperties, "Container group properties should not be nil")
|
||||||
|
assert.NotNil(t, cg.ContainerGroupProperties.Containers, "Containers should not be nil")
|
||||||
|
assert.Equal(t, 1, len(cg.ContainerGroupProperties.Containers), "1 Container is expected")
|
||||||
|
assert.Equal(t, "nginx", cg.ContainerGroupProperties.Containers[0].Name, "Container nginx is expected")
|
||||||
|
assert.NotNil(t, cg.Containers[0].ReadinessProbe, "Readiness probe expected")
|
||||||
|
assert.Equal(t, cg.Containers[0].ReadinessProbe.InitialDelaySeconds, 10, "Initial Probe Delay doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].ReadinessProbe.Period, 5, "Probe Period doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].ReadinessProbe.TimeoutSeconds, 60, "Probe Timeout doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].ReadinessProbe.SuccessThreshold, 3, "Probe Success Threshold doesn't match")
|
||||||
|
assert.Equal(t, cg.Containers[0].ReadinessProbe.FailureThreshold, 5, "Probe Failure Threshold doesn't match")
|
||||||
|
assert.NotNil(t, cg.Containers[0].ReadinessProbe.HTTPGet, "Expected an HTTP Get Probe")
|
||||||
|
|
||||||
|
pod := &v1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: podName,
|
||||||
|
Namespace: podNamespace,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
Containers: []v1.Container{
|
||||||
|
v1.Container{
|
||||||
|
Name: "nginx",
|
||||||
|
ReadinessProbe: &v1.Probe{
|
||||||
|
Handler: v1.Handler{
|
||||||
|
HTTPGet: &v1.HTTPGetAction{
|
||||||
|
Port: intstr.FromString("8080"),
|
||||||
|
Path: "/",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
InitialDelaySeconds: 10,
|
||||||
|
PeriodSeconds: 5,
|
||||||
|
TimeoutSeconds: 60,
|
||||||
|
SuccessThreshold: 3,
|
||||||
|
FailureThreshold: 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := provider.CreatePod(pod); err != nil {
|
||||||
|
t.Fatal("Failed to create pod", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.StatusOK, cg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user