mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 01:28:45 +01:00
1608 lines
40 KiB
Go
1608 lines
40 KiB
Go
package cache
|
|
|
|
import (
|
|
"sort"
|
|
"testing"
|
|
|
|
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/kube"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"sigs.k8s.io/yaml"
|
|
|
|
"github.com/argoproj/argo-cd/v3/common"
|
|
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
|
|
"github.com/argoproj/argo-cd/v3/util/argo/normalizers"
|
|
"github.com/argoproj/argo-cd/v3/util/errors"
|
|
)
|
|
|
|
func strToUnstructured(jsonStr string) *unstructured.Unstructured {
|
|
obj := make(map[string]any)
|
|
err := yaml.Unmarshal([]byte(jsonStr), &obj)
|
|
errors.CheckError(err)
|
|
return &unstructured.Unstructured{Object: obj}
|
|
}
|
|
|
|
var (
|
|
testService = strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
resourceVersion: "123"
|
|
uid: "4"
|
|
spec:
|
|
selector:
|
|
app: guestbook
|
|
type: LoadBalancer
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- hostname: localhost`)
|
|
|
|
testLinkAnnotatedService = strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
resourceVersion: "123"
|
|
uid: "4"
|
|
annotations:
|
|
link.argocd.argoproj.io/external-link: http://my-grafana.example.com/pre-generated-link
|
|
spec:
|
|
selector:
|
|
app: guestbook
|
|
type: LoadBalancer
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- hostname: localhost`)
|
|
|
|
testIngress = strToUnstructured(`
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
uid: "4"
|
|
spec:
|
|
backend:
|
|
serviceName: not-found-service
|
|
servicePort: 443
|
|
rules:
|
|
- host: helm-guestbook.example.com
|
|
http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: https
|
|
path: /
|
|
tls:
|
|
- host: helm-guestbook.example.com
|
|
secretName: my-tls-secret
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
testLinkAnnotatedIngress = strToUnstructured(`
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
uid: "4"
|
|
annotations:
|
|
link.argocd.argoproj.io/external-link: http://my-grafana.example.com/ingress-link
|
|
spec:
|
|
backend:
|
|
serviceName: not-found-service
|
|
servicePort: 443
|
|
rules:
|
|
- host: helm-guestbook.example.com
|
|
http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: https
|
|
path: /
|
|
tls:
|
|
- host: helm-guestbook.example.com
|
|
secretName: my-tls-secret
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
testIgnoreDefaultLinksIngress = strToUnstructured(`
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
uid: "4"
|
|
annotations:
|
|
link.argocd.argoproj.io/external-link: http://my-grafana.example.com/ingress-link
|
|
argocd.argoproj.io/ignore-default-links: "true"
|
|
spec:
|
|
backend:
|
|
serviceName: not-found-service
|
|
servicePort: 443
|
|
rules:
|
|
- host: helm-guestbook.example.com
|
|
http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: https
|
|
path: /
|
|
tls:
|
|
- host: helm-guestbook.example.com
|
|
secretName: my-tls-secret
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
testIngressWildCardPath = strToUnstructured(`
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
uid: "4"
|
|
spec:
|
|
backend:
|
|
serviceName: not-found-service
|
|
servicePort: 443
|
|
rules:
|
|
- host: helm-guestbook.example.com
|
|
http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /*
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: https
|
|
path: /*
|
|
tls:
|
|
- host: helm-guestbook.example.com
|
|
secretName: my-tls-secret
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
testIngressWithoutTLS = strToUnstructured(`
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
uid: "4"
|
|
spec:
|
|
backend:
|
|
serviceName: not-found-service
|
|
servicePort: 443
|
|
rules:
|
|
- host: helm-guestbook.example.com
|
|
http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: https
|
|
path: /
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
testIngressNetworkingV1 = strToUnstructured(`
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
uid: "4"
|
|
spec:
|
|
backend:
|
|
service:
|
|
name: not-found-service
|
|
port:
|
|
number: 443
|
|
rules:
|
|
- host: helm-guestbook.example.com
|
|
http:
|
|
paths:
|
|
- backend:
|
|
service:
|
|
name: helm-guestbook
|
|
port:
|
|
number: 443
|
|
path: /
|
|
- backend:
|
|
service:
|
|
name: helm-guestbook
|
|
port:
|
|
name: https
|
|
path: /
|
|
tls:
|
|
- host: helm-guestbook.example.com
|
|
secretName: my-tls-secret
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
testIstioVirtualService = strToUnstructured(`
|
|
apiVersion: networking.istio.io/v1alpha3
|
|
kind: VirtualService
|
|
metadata:
|
|
name: hello-world
|
|
namespace: demo
|
|
spec:
|
|
http:
|
|
- match:
|
|
- uri:
|
|
prefix: "/1"
|
|
route:
|
|
- destination:
|
|
host: service_full.demo.svc.cluster.local
|
|
- destination:
|
|
host: service_namespace.namespace
|
|
- match:
|
|
- uri:
|
|
prefix: "/2"
|
|
route:
|
|
- destination:
|
|
host: service
|
|
`)
|
|
|
|
testIstioServiceEntry = strToUnstructured(`
|
|
apiVersion: networking.istio.io/v1beta1
|
|
kind: ServiceEntry
|
|
metadata:
|
|
name: echo
|
|
spec:
|
|
exportTo:
|
|
- '*'
|
|
hosts:
|
|
- echo.internal
|
|
location: MESH_INTERNAL
|
|
ports:
|
|
- name: http
|
|
number: 80
|
|
protocol: HTTP
|
|
targetPort: 5678
|
|
resolution: DNS
|
|
|
|
workloadSelector:
|
|
labels:
|
|
app.kubernetes.io/name: echo-2
|
|
`)
|
|
)
|
|
|
|
// These tests are equivalent to tests in ui/src/app/applications/components/utils.test.tsx. If you update tests here,
|
|
// please make sure to update the equivalent tests in the UI.
|
|
func TestGetPodInfo(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("TestGetPodInfo", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: helm-guestbook-pod
|
|
namespace: default
|
|
ownerReferences:
|
|
- apiVersion: extensions/v1beta1
|
|
kind: ReplicaSet
|
|
name: helm-guestbook-rs
|
|
resourceVersion: "123"
|
|
labels:
|
|
app: guestbook
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- image: bar
|
|
resources:
|
|
requests:
|
|
memory: 128Mi
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
{Name: common.PodRequestsCPU, Value: "0"}, // strings imported from common
|
|
{Name: common.PodRequestsMEM, Value: "134217728000"},
|
|
}, info.Info)
|
|
assert.Equal(t, []string{"bar"}, info.Images)
|
|
assert.Equal(t, &PodInfo{
|
|
NodeName: "minikube",
|
|
ResourceRequests: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("128Mi")},
|
|
}, info.PodInfo)
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{Labels: map[string]string{"app": "guestbook"}}, info.NetworkingInfo)
|
|
})
|
|
|
|
t.Run("TestGetPodWithInitialContainerInfo", func(t *testing.T) {
|
|
pod := strToUnstructured(`
|
|
apiVersion: "v1"
|
|
kind: "Pod"
|
|
metadata:
|
|
labels:
|
|
app: "app-with-initial-container"
|
|
name: "app-with-initial-container-5f46976fdb-vd6rv"
|
|
namespace: "default"
|
|
ownerReferences:
|
|
- apiVersion: "apps/v1"
|
|
kind: "ReplicaSet"
|
|
name: "app-with-initial-container-5f46976fdb"
|
|
spec:
|
|
containers:
|
|
- image: "alpine:latest"
|
|
imagePullPolicy: "Always"
|
|
name: "app-with-initial-container"
|
|
initContainers:
|
|
- image: "alpine:latest"
|
|
imagePullPolicy: "Always"
|
|
name: "app-with-initial-container-logshipper"
|
|
nodeName: "minikube"
|
|
status:
|
|
containerStatuses:
|
|
- image: "alpine:latest"
|
|
name: "app-with-initial-container"
|
|
ready: true
|
|
restartCount: 0
|
|
started: true
|
|
state:
|
|
running:
|
|
startedAt: "2024-10-08T08:44:25Z"
|
|
initContainerStatuses:
|
|
- image: "alpine:latest"
|
|
name: "app-with-initial-container-logshipper"
|
|
ready: true
|
|
restartCount: 0
|
|
started: false
|
|
state:
|
|
terminated:
|
|
exitCode: 0
|
|
reason: "Completed"
|
|
phase: "Running"
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Running"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "1/1"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
t.Run("TestGetPodWithInitialContainerInfoWithResources", func(t *testing.T) {
|
|
pod := strToUnstructured(`
|
|
apiVersion: "v1"
|
|
kind: "Pod"
|
|
metadata:
|
|
labels:
|
|
app: "app-with-initial-container"
|
|
name: "app-with-initial-container-5f46976fdb-vd6rv"
|
|
namespace: "default"
|
|
ownerReferences:
|
|
- apiVersion: "apps/v1"
|
|
kind: "ReplicaSet"
|
|
name: "app-with-initial-container-5f46976fdb"
|
|
spec:
|
|
containers:
|
|
- image: "alpine:latest"
|
|
imagePullPolicy: "Always"
|
|
name: "app-with-initial-container"
|
|
resources:
|
|
requests:
|
|
cpu: "100m"
|
|
memory: "128Mi"
|
|
limits:
|
|
cpu: "500m"
|
|
memory: "512Mi"
|
|
initContainers:
|
|
- image: "alpine:latest"
|
|
imagePullPolicy: "Always"
|
|
name: "app-with-initial-container-logshipper"
|
|
resources:
|
|
requests:
|
|
cpu: "50m"
|
|
memory: "64Mi"
|
|
limits:
|
|
cpu: "250m"
|
|
memory: "256Mi"
|
|
nodeName: "minikube"
|
|
status:
|
|
containerStatuses:
|
|
- image: "alpine:latest"
|
|
name: "app-with-initial-container"
|
|
ready: true
|
|
restartCount: 0
|
|
started: true
|
|
state:
|
|
running:
|
|
startedAt: "2024-10-08T08:44:25Z"
|
|
initContainerStatuses:
|
|
- image: "alpine:latest"
|
|
name: "app-with-initial-container-logshipper"
|
|
ready: true
|
|
restartCount: 0
|
|
started: false
|
|
state:
|
|
terminated:
|
|
exitCode: 0
|
|
reason: "Completed"
|
|
phase: "Running"
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Running"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "1/1"},
|
|
{Name: common.PodRequestsCPU, Value: "100"},
|
|
{Name: common.PodRequestsMEM, Value: "134217728000"},
|
|
}, info.Info)
|
|
})
|
|
t.Run("TestGetPodInfoWithSidecar", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
labels:
|
|
app: app-with-sidecar
|
|
name: app-with-sidecar-6664cc788c-lqlrp
|
|
namespace: default
|
|
ownerReferences:
|
|
- apiVersion: apps/v1
|
|
kind: ReplicaSet
|
|
name: app-with-sidecar-6664cc788c
|
|
spec:
|
|
containers:
|
|
- image: 'docker.m.daocloud.io/library/alpine:latest'
|
|
imagePullPolicy: Always
|
|
name: app-with-sidecar
|
|
initContainers:
|
|
- image: 'docker.m.daocloud.io/library/alpine:latest'
|
|
imagePullPolicy: Always
|
|
name: logshipper
|
|
restartPolicy: Always
|
|
nodeName: minikube
|
|
status:
|
|
containerStatuses:
|
|
- image: 'docker.m.daocloud.io/library/alpine:latest'
|
|
name: app-with-sidecar
|
|
ready: true
|
|
restartCount: 0
|
|
started: true
|
|
state:
|
|
running:
|
|
startedAt: '2024-10-08T08:39:43Z'
|
|
initContainerStatuses:
|
|
- image: 'docker.m.daocloud.io/library/alpine:latest'
|
|
name: logshipper
|
|
ready: true
|
|
restartCount: 0
|
|
started: true
|
|
state:
|
|
running:
|
|
startedAt: '2024-10-08T08:39:40Z'
|
|
phase: Running
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Running"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "2/2"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
t.Run("TestGetPodInfoWithInitialContainer", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
generateName: myapp-long-exist-56b7d8794d-
|
|
labels:
|
|
app: myapp-long-exist
|
|
name: myapp-long-exist-56b7d8794d-pbgrd
|
|
namespace: linghao
|
|
ownerReferences:
|
|
- apiVersion: apps/v1
|
|
kind: ReplicaSet
|
|
name: myapp-long-exist-56b7d8794d
|
|
spec:
|
|
containers:
|
|
- image: alpine:latest
|
|
imagePullPolicy: Always
|
|
name: myapp-long-exist
|
|
initContainers:
|
|
- image: alpine:latest
|
|
imagePullPolicy: Always
|
|
name: myapp-long-exist-logshipper
|
|
nodeName: minikube
|
|
status:
|
|
containerStatuses:
|
|
- image: alpine:latest
|
|
name: myapp-long-exist
|
|
ready: false
|
|
restartCount: 0
|
|
started: false
|
|
state:
|
|
waiting:
|
|
reason: PodInitializing
|
|
initContainerStatuses:
|
|
- image: alpine:latest
|
|
name: myapp-long-exist-logshipper
|
|
ready: false
|
|
restartCount: 0
|
|
started: true
|
|
state:
|
|
running:
|
|
startedAt: '2024-10-09T08:03:45Z'
|
|
phase: Pending
|
|
startTime: '2024-10-09T08:02:39Z'
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Init:0/1"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod has 2 restartable init containers, the first one running but not started.
|
|
t.Run("TestGetPodInfoWithRestartableInitContainer", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test1
|
|
spec:
|
|
initContainers:
|
|
- name: restartable-init-1
|
|
restartPolicy: Always
|
|
- name: restartable-init-2
|
|
restartPolicy: Always
|
|
containers:
|
|
- name: container
|
|
nodeName: minikube
|
|
status:
|
|
phase: Pending
|
|
initContainerStatuses:
|
|
- name: restartable-init-1
|
|
ready: false
|
|
restartCount: 3
|
|
state:
|
|
running: {}
|
|
started: false
|
|
lastTerminationState:
|
|
terminated:
|
|
finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time
|
|
- name: restartable-init-2
|
|
ready: false
|
|
state:
|
|
waiting: {}
|
|
started: false
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
waiting: {}
|
|
conditions:
|
|
- type: ContainersReady
|
|
status: "False"
|
|
- type: Initialized
|
|
status: "False"
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Init:0/2"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/3"},
|
|
{Name: "Restart Count", Value: "3"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod has 2 restartable init containers, the first one started and the second one running but not started.
|
|
t.Run("TestGetPodInfoWithPartiallyStartedInitContainers", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test1
|
|
spec:
|
|
initContainers:
|
|
- name: restartable-init-1
|
|
restartPolicy: Always
|
|
- name: restartable-init-2
|
|
restartPolicy: Always
|
|
containers:
|
|
- name: container
|
|
nodeName: minikube
|
|
status:
|
|
phase: Pending
|
|
initContainerStatuses:
|
|
- name: restartable-init-1
|
|
ready: false
|
|
restartCount: 3
|
|
state:
|
|
running: {}
|
|
started: true
|
|
lastTerminationState:
|
|
terminated:
|
|
finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time
|
|
- name: restartable-init-2
|
|
ready: false
|
|
state:
|
|
running: {}
|
|
started: false
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
waiting: {}
|
|
conditions:
|
|
- type: ContainersReady
|
|
status: "False"
|
|
- type: Initialized
|
|
status: "False"
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Init:1/2"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/3"},
|
|
{Name: "Restart Count", Value: "3"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod has 2 restartable init containers started and 1 container running
|
|
t.Run("TestGetPodInfoWithStartedInitContainers", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test2
|
|
spec:
|
|
initContainers:
|
|
- name: restartable-init-1
|
|
restartPolicy: Always
|
|
- name: restartable-init-2
|
|
restartPolicy: Always
|
|
containers:
|
|
- name: container
|
|
nodeName: minikube
|
|
status:
|
|
phase: Running
|
|
initContainerStatuses:
|
|
- name: restartable-init-1
|
|
ready: false
|
|
restartCount: 3
|
|
state:
|
|
running: {}
|
|
started: true
|
|
lastTerminationState:
|
|
terminated:
|
|
finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time
|
|
- name: restartable-init-2
|
|
ready: false
|
|
state:
|
|
running: {}
|
|
started: true
|
|
containerStatuses:
|
|
- ready: true
|
|
restartCount: 4
|
|
state:
|
|
running: {}
|
|
lastTerminationState:
|
|
terminated:
|
|
finishedAt: "2023-10-01T00:00:00Z" # Replace with actual time
|
|
conditions:
|
|
- type: ContainersReady
|
|
status: "False"
|
|
- type: Initialized
|
|
status: "True"
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Running"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "1/3"},
|
|
{Name: "Restart Count", Value: "7"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod has 1 init container restarting and 1 container not running
|
|
t.Run("TestGetPodInfoWithNormalInitContainer", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test7
|
|
spec:
|
|
initContainers:
|
|
- name: init-container
|
|
containers:
|
|
- name: main-container
|
|
nodeName: minikube
|
|
status:
|
|
phase: podPhase
|
|
initContainerStatuses:
|
|
- ready: false
|
|
restartCount: 3
|
|
state:
|
|
running: {}
|
|
lastTerminationState:
|
|
terminated:
|
|
finishedAt: "2023-10-01T00:00:00Z" # Replace with the actual time
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
waiting: {}
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Init:0/1"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
{Name: "Restart Count", Value: "3"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod condition succeed
|
|
t.Run("TestPodConditionSucceeded", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test8
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container
|
|
status:
|
|
phase: Succeeded
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
terminated:
|
|
reason: Completed
|
|
exitCode: 0
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Completed"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod condition succeed which had some allocated resources
|
|
t.Run("TestPodConditionSucceededWithResources", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test8
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container
|
|
resources:
|
|
requests:
|
|
cpu: "50m"
|
|
memory: "64Mi"
|
|
limits:
|
|
cpu: "250m"
|
|
memory: "256Mi"
|
|
status:
|
|
phase: Succeeded
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
terminated:
|
|
reason: Completed
|
|
exitCode: 0
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Completed"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod condition failed
|
|
t.Run("TestPodConditionFailed", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test9
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container
|
|
status:
|
|
phase: Failed
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
terminated:
|
|
reason: Error
|
|
exitCode: 1
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Error"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod condition failed with allocated resources
|
|
|
|
t.Run("TestPodConditionFailedWithResources", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test9
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container
|
|
resources:
|
|
requests:
|
|
cpu: "50m"
|
|
memory: "64Mi"
|
|
limits:
|
|
cpu: "250m"
|
|
memory: "256Mi"
|
|
status:
|
|
phase: Failed
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
terminated:
|
|
reason: Error
|
|
exitCode: 1
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Error"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod condition succeed with deletion
|
|
t.Run("TestPodConditionSucceededWithDeletion", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test10
|
|
deletionTimestamp: "2023-10-01T00:00:00Z"
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container
|
|
status:
|
|
phase: Succeeded
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
terminated:
|
|
reason: Completed
|
|
exitCode: 0
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Completed"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod condition running with deletion
|
|
t.Run("TestPodConditionRunningWithDeletion", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test11
|
|
deletionTimestamp: "2023-10-01T00:00:00Z"
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container
|
|
status:
|
|
phase: Running
|
|
containerStatuses:
|
|
- ready: false
|
|
restartCount: 0
|
|
state:
|
|
running: {}
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Terminating"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test pod condition pending with deletion
|
|
t.Run("TestPodConditionPendingWithDeletion", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test12
|
|
deletionTimestamp: "2023-10-01T00:00:00Z"
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container
|
|
status:
|
|
phase: Pending
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "Terminating"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/1"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
|
|
// Test PodScheduled condition with reason SchedulingGated
|
|
t.Run("TestPodScheduledWithSchedulingGated", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
pod := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: test13
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- name: container1
|
|
- name: container2
|
|
status:
|
|
phase: podPhase
|
|
conditions:
|
|
- type: PodScheduled
|
|
status: "False"
|
|
reason: SchedulingGated
|
|
`)
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(pod, info, []string{})
|
|
assert.Equal(t, []v1alpha1.InfoItem{
|
|
{Name: "Status Reason", Value: "SchedulingGated"},
|
|
{Name: "Node", Value: "minikube"},
|
|
{Name: "Containers", Value: "0/2"},
|
|
{Name: common.PodRequestsCPU, Value: "0"},
|
|
{Name: common.PodRequestsMEM, Value: "0"},
|
|
}, info.Info)
|
|
})
|
|
}
|
|
|
|
func TestGetNodeInfo(t *testing.T) {
|
|
node := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Node
|
|
metadata:
|
|
name: minikube
|
|
labels:
|
|
foo: bar
|
|
spec: {}
|
|
status:
|
|
capacity:
|
|
cpu: "6"
|
|
memory: 6091320Ki
|
|
nodeInfo:
|
|
architecture: amd64
|
|
operatingSystem: linux
|
|
osImage: Ubuntu 20.04 LTS
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(node, info, []string{})
|
|
assert.Equal(t, &NodeInfo{
|
|
Name: "minikube",
|
|
Capacity: corev1.ResourceList{corev1.ResourceMemory: resource.MustParse("6091320Ki"), corev1.ResourceCPU: resource.MustParse("6")},
|
|
SystemInfo: corev1.NodeSystemInfo{Architecture: "amd64", OperatingSystem: "linux", OSImage: "Ubuntu 20.04 LTS"},
|
|
Labels: map[string]string{"foo": "bar"},
|
|
}, info.NodeInfo)
|
|
}
|
|
|
|
func TestGetServiceInfo(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testService, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
TargetLabels: map[string]string{"app": "guestbook"},
|
|
Ingress: []corev1.LoadBalancerIngress{{Hostname: "localhost"}},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
|
|
func TestGetLinkAnnotatedServiceInfo(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testLinkAnnotatedService, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
TargetLabels: map[string]string{"app": "guestbook"},
|
|
Ingress: []corev1.LoadBalancerIngress{{Hostname: "localhost"}},
|
|
ExternalURLs: []string{"http://my-grafana.example.com/pre-generated-link"},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
|
|
func TestGetIstioVirtualServiceInfo(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testIstioVirtualService, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
require.NotNil(t, info.NetworkingInfo)
|
|
require.NotNil(t, info.NetworkingInfo.TargetRefs)
|
|
assert.Contains(t, info.NetworkingInfo.TargetRefs, v1alpha1.ResourceRef{
|
|
Kind: kube.ServiceKind,
|
|
Name: "service_full",
|
|
Namespace: "demo",
|
|
})
|
|
assert.Contains(t, info.NetworkingInfo.TargetRefs, v1alpha1.ResourceRef{
|
|
Kind: kube.ServiceKind,
|
|
Name: "service_namespace",
|
|
Namespace: "namespace",
|
|
})
|
|
assert.Contains(t, info.NetworkingInfo.TargetRefs, v1alpha1.ResourceRef{
|
|
Kind: kube.ServiceKind,
|
|
Name: "service",
|
|
Namespace: "demo",
|
|
})
|
|
}
|
|
|
|
func TestGetIstioServiceEntryInfo(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testIstioServiceEntry, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
require.NotNil(t, info.NetworkingInfo)
|
|
require.NotNil(t, info.NetworkingInfo.TargetRefs)
|
|
assert.Contains(t, info.NetworkingInfo.TargetRefs, v1alpha1.ResourceRef{
|
|
Kind: kube.PodKind,
|
|
})
|
|
|
|
assert.Equal(t, map[string]string{
|
|
"app.kubernetes.io/name": "echo-2",
|
|
}, info.NetworkingInfo.TargetLabels)
|
|
}
|
|
|
|
func TestGetIngressInfo(t *testing.T) {
|
|
tests := []struct {
|
|
Ingress *unstructured.Unstructured
|
|
}{
|
|
{testIngress},
|
|
{testIngressNetworkingV1},
|
|
}
|
|
for _, tc := range tests {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(tc.Ingress, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
|
|
return info.NetworkingInfo.TargetRefs[i].Name < info.NetworkingInfo.TargetRefs[j].Name
|
|
})
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
Ingress: []corev1.LoadBalancerIngress{{IP: "107.178.210.11"}},
|
|
TargetRefs: []v1alpha1.ResourceRef{{
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "helm-guestbook",
|
|
}, {
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "not-found-service",
|
|
}},
|
|
ExternalURLs: []string{"https://helm-guestbook.example.com/"},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
}
|
|
|
|
func TestGetLinkAnnotatedIngressInfo(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testLinkAnnotatedIngress, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
|
|
return info.NetworkingInfo.TargetRefs[i].Name < info.NetworkingInfo.TargetRefs[j].Name
|
|
})
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
Ingress: []corev1.LoadBalancerIngress{{IP: "107.178.210.11"}},
|
|
TargetRefs: []v1alpha1.ResourceRef{{
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "helm-guestbook",
|
|
}, {
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "not-found-service",
|
|
}},
|
|
ExternalURLs: []string{"http://my-grafana.example.com/ingress-link", "https://helm-guestbook.example.com/"},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
|
|
func TestGetIgnoreDefaultLinksIngressInfo(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testIgnoreDefaultLinksIngress, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
|
|
return info.NetworkingInfo.TargetRefs[i].Name < info.NetworkingInfo.TargetRefs[j].Name
|
|
})
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
Ingress: []corev1.LoadBalancerIngress{{IP: "107.178.210.11"}},
|
|
TargetRefs: []v1alpha1.ResourceRef{{
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "helm-guestbook",
|
|
}, {
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "not-found-service",
|
|
}},
|
|
ExternalURLs: []string{"http://my-grafana.example.com/ingress-link"},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
|
|
func TestGetIngressInfoWildCardPath(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testIngressWildCardPath, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
|
|
return info.NetworkingInfo.TargetRefs[i].Name < info.NetworkingInfo.TargetRefs[j].Name
|
|
})
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
Ingress: []corev1.LoadBalancerIngress{{IP: "107.178.210.11"}},
|
|
TargetRefs: []v1alpha1.ResourceRef{{
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "helm-guestbook",
|
|
}, {
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "not-found-service",
|
|
}},
|
|
ExternalURLs: []string{"https://helm-guestbook.example.com/"},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
|
|
func TestGetIngressInfoWithoutTls(t *testing.T) {
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(testIngressWithoutTLS, info, []string{})
|
|
assert.Empty(t, info.Info)
|
|
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
|
|
return info.NetworkingInfo.TargetRefs[i].Name < info.NetworkingInfo.TargetRefs[j].Name
|
|
})
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
Ingress: []corev1.LoadBalancerIngress{{IP: "107.178.210.11"}},
|
|
TargetRefs: []v1alpha1.ResourceRef{{
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "helm-guestbook",
|
|
}, {
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "not-found-service",
|
|
}},
|
|
ExternalURLs: []string{"http://helm-guestbook.example.com/"},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
|
|
func TestGetIngressInfoWithHost(t *testing.T) {
|
|
ingress := strToUnstructured(`
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
spec:
|
|
rules:
|
|
- http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /
|
|
tls:
|
|
- secretName: my-tls
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(ingress, info, []string{})
|
|
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
Ingress: []corev1.LoadBalancerIngress{{IP: "107.178.210.11"}},
|
|
TargetRefs: []v1alpha1.ResourceRef{{
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "helm-guestbook",
|
|
}},
|
|
ExternalURLs: []string{"https://107.178.210.11/"},
|
|
}, info.NetworkingInfo)
|
|
}
|
|
|
|
func TestGetIngressInfoNoHost(t *testing.T) {
|
|
ingress := strToUnstructured(`
|
|
apiVersion: extensions/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
spec:
|
|
rules:
|
|
- http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /
|
|
tls:
|
|
- secretName: my-tls
|
|
`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(ingress, info, []string{})
|
|
|
|
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
|
|
TargetRefs: []v1alpha1.ResourceRef{{
|
|
Namespace: "default",
|
|
Group: "",
|
|
Kind: kube.ServiceKind,
|
|
Name: "helm-guestbook",
|
|
}},
|
|
}, info.NetworkingInfo)
|
|
assert.Empty(t, info.NetworkingInfo.ExternalURLs)
|
|
}
|
|
|
|
func TestExternalUrlWithSubPath(t *testing.T) {
|
|
ingress := strToUnstructured(`
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
spec:
|
|
rules:
|
|
- http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /my/sub/path/
|
|
tls:
|
|
- secretName: my-tls
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(ingress, info, []string{})
|
|
|
|
expectedExternalUrls := []string{"https://107.178.210.11/my/sub/path/"}
|
|
assert.Equal(t, expectedExternalUrls, info.NetworkingInfo.ExternalURLs)
|
|
}
|
|
|
|
func TestExternalUrlWithMultipleSubPaths(t *testing.T) {
|
|
ingress := strToUnstructured(`
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
spec:
|
|
rules:
|
|
- host: helm-guestbook.example.com
|
|
http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
path: /my/sub/path/
|
|
- backend:
|
|
serviceName: helm-guestbook-2
|
|
servicePort: 443
|
|
path: /my/sub/path/2
|
|
- backend:
|
|
serviceName: helm-guestbook-3
|
|
servicePort: 443
|
|
tls:
|
|
- secretName: my-tls
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(ingress, info, []string{})
|
|
|
|
expectedExternalUrls := []string{"https://helm-guestbook.example.com/my/sub/path/", "https://helm-guestbook.example.com/my/sub/path/2", "https://helm-guestbook.example.com"}
|
|
actualURLs := info.NetworkingInfo.ExternalURLs
|
|
sort.Strings(expectedExternalUrls)
|
|
sort.Strings(actualURLs)
|
|
assert.Equal(t, expectedExternalUrls, actualURLs)
|
|
}
|
|
|
|
func TestExternalUrlWithNoSubPath(t *testing.T) {
|
|
ingress := strToUnstructured(`
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
spec:
|
|
rules:
|
|
- http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
tls:
|
|
- secretName: my-tls
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(ingress, info, []string{})
|
|
|
|
expectedExternalUrls := []string{"https://107.178.210.11"}
|
|
assert.Equal(t, expectedExternalUrls, info.NetworkingInfo.ExternalURLs)
|
|
}
|
|
|
|
func TestExternalUrlWithNetworkingApi(t *testing.T) {
|
|
ingress := strToUnstructured(`
|
|
apiVersion: networking.k8s.io/v1beta1
|
|
kind: Ingress
|
|
metadata:
|
|
name: helm-guestbook
|
|
namespace: default
|
|
spec:
|
|
rules:
|
|
- http:
|
|
paths:
|
|
- backend:
|
|
serviceName: helm-guestbook
|
|
servicePort: 443
|
|
tls:
|
|
- secretName: my-tls
|
|
status:
|
|
loadBalancer:
|
|
ingress:
|
|
- ip: 107.178.210.11`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(ingress, info, []string{})
|
|
|
|
expectedExternalUrls := []string{"https://107.178.210.11"}
|
|
assert.Equal(t, expectedExternalUrls, info.NetworkingInfo.ExternalURLs)
|
|
}
|
|
|
|
func TestCustomLabel(t *testing.T) {
|
|
configmap := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: cm`)
|
|
|
|
info := &ResourceInfo{}
|
|
populateNodeInfo(configmap, info, []string{"my-label"})
|
|
|
|
assert.Empty(t, info.Info)
|
|
|
|
configmap = strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: cm
|
|
labels:
|
|
my-label: value`)
|
|
|
|
info = &ResourceInfo{}
|
|
populateNodeInfo(configmap, info, []string{"my-label", "other-label"})
|
|
|
|
assert.Len(t, info.Info, 1)
|
|
assert.Equal(t, "my-label", info.Info[0].Name)
|
|
assert.Equal(t, "value", info.Info[0].Value)
|
|
|
|
configmap = strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: cm
|
|
labels:
|
|
my-label: value
|
|
other-label: value2`)
|
|
|
|
info = &ResourceInfo{}
|
|
populateNodeInfo(configmap, info, []string{"my-label", "other-label"})
|
|
|
|
assert.Len(t, info.Info, 2)
|
|
assert.Equal(t, "my-label", info.Info[0].Name)
|
|
assert.Equal(t, "value", info.Info[0].Value)
|
|
assert.Equal(t, "other-label", info.Info[1].Name)
|
|
assert.Equal(t, "value2", info.Info[1].Value)
|
|
}
|
|
|
|
func TestManifestHash(t *testing.T) {
|
|
manifest := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: helm-guestbook-pod
|
|
namespace: default
|
|
ownerReferences:
|
|
- apiVersion: extensions/v1beta1
|
|
kind: ReplicaSet
|
|
name: helm-guestbook-rs
|
|
resourceVersion: "123"
|
|
labels:
|
|
app: guestbook
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- image: bar
|
|
resources:
|
|
requests:
|
|
memory: 128Mi
|
|
`)
|
|
|
|
ignores := []v1alpha1.ResourceIgnoreDifferences{
|
|
{
|
|
Group: "*",
|
|
Kind: "*",
|
|
JSONPointers: []string{"/metadata/resourceVersion"},
|
|
},
|
|
}
|
|
|
|
data, _ := strToUnstructured(`
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: helm-guestbook-pod
|
|
namespace: default
|
|
ownerReferences:
|
|
- apiVersion: extensions/v1beta1
|
|
kind: ReplicaSet
|
|
name: helm-guestbook-rs
|
|
labels:
|
|
app: guestbook
|
|
spec:
|
|
nodeName: minikube
|
|
containers:
|
|
- image: bar
|
|
resources:
|
|
requests:
|
|
memory: 128Mi
|
|
`).MarshalJSON()
|
|
|
|
expected := hash(data)
|
|
|
|
hash, err := generateManifestHash(manifest, ignores, nil, normalizers.IgnoreNormalizerOpts{})
|
|
assert.Equal(t, expected, hash)
|
|
assert.NoError(t, err)
|
|
}
|