Skip to content

Commit

Permalink
Deriving podIps of the pods for k8s service if target pod has service…
Browse files Browse the repository at this point in the history
…Mesh sidecar

Signed-off-by: Shubham Chaudhary <shubham.chaudhary@harness.io>
  • Loading branch information
ispeakc0de committed Sep 12, 2022
1 parent 718e8a8 commit 392d166
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 10 deletions.
71 changes: 63 additions & 8 deletions chaoslib/litmus/network-chaos/lib/network-chaos.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package lib

import (
"context"
"fmt"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"net"
"strconv"
"strings"
Expand All @@ -19,6 +21,8 @@ import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var serviceMesh = []string{"istio", "envoy"}

//PrepareAndInjectChaos contains the prepration & injection steps
func PrepareAndInjectChaos(experimentsDetails *experimentTypes.ExperimentDetails, clients clients.ClientSets, resultDetails *types.ResultDetails, eventsDetails *types.EventDetails, chaosDetails *types.ChaosDetails, args string) error {

Expand Down Expand Up @@ -103,11 +107,6 @@ func PrepareAndInjectChaos(experimentsDetails *experimentTypes.ExperimentDetails
}
}

experimentsDetails.DestinationIPs, err = GetTargetIps(experimentsDetails.DestinationIPs, experimentsDetails.DestinationHosts)
if err != nil {
return err
}

if experimentsDetails.EngineName != "" {
if err := common.SetHelperData(chaosDetails, experimentsDetails.SetHelperData, clients); err != nil {
return err
Expand Down Expand Up @@ -146,6 +145,11 @@ func injectChaosInSerialMode(experimentsDetails *experimentTypes.ExperimentDetai
// creating the helper pod to perform network chaos
for _, pod := range targetPodList.Items {

experimentsDetails.DestinationIPs, err = GetTargetIps(experimentsDetails.DestinationIPs, experimentsDetails.DestinationHosts, clients, isServiceMeshEnabledForPod(pod))
if err != nil {
return err
}

//Get the target container name of the application pod
if !experimentsDetails.IsTargetContainerProvided {
experimentsDetails.TargetContainer, err = common.GetTargetContainer(experimentsDetails.AppNS, pod.Name, clients)
Expand Down Expand Up @@ -207,6 +211,11 @@ func injectChaosInParallelMode(experimentsDetails *experimentTypes.ExperimentDet
// creating the helper pod to perform network chaos
for _, pod := range targetPodList.Items {

experimentsDetails.DestinationIPs, err = GetTargetIps(experimentsDetails.DestinationIPs, experimentsDetails.DestinationHosts, clients, isServiceMeshEnabledForPod(pod))
if err != nil {
return err
}

//Get the target container name of the application pod
//It checks the empty target container for the first iteration only
if !experimentsDetails.IsTargetContainerProvided {
Expand Down Expand Up @@ -350,9 +359,9 @@ func getPodEnv(experimentsDetails *experimentTypes.ExperimentDetails, podName, a
// GetTargetIps return the comma separated target ips
// It fetch the ips from the target ips (if defined by users)
// it append the ips from the host, if target host is provided
func GetTargetIps(targetIPs, targetHosts string) (string, error) {
func GetTargetIps(targetIPs, targetHosts string, clients clients.ClientSets, serviceMesh bool) (string, error) {

ipsFromHost, err := getIpsForTargetHosts(targetHosts)
ipsFromHost, err := getIpsForTargetHosts(targetHosts, clients, serviceMesh)
if err != nil {
return "", err
}
Expand All @@ -364,15 +373,51 @@ func GetTargetIps(targetIPs, targetHosts string) (string, error) {
return targetIPs, nil
}

// it derive the pod ips from the kubernetes service
func getPodIPFromService(host string, clients clients.ClientSets) ([]string, error) {
var ips []string
svcFields := strings.Split(host, ".")
if len(svcFields) != 5 {
return ips, fmt.Errorf("provide the valid FQDN for service in '<svc-name>.<namespace>.svc.cluster.local format, host: %v", host)
}
svcName, svcNs := svcFields[0], svcFields[1]
svc, err := clients.KubeClient.CoreV1().Services(svcNs).Get(context.Background(), svcName, v1.GetOptions{})
if err != nil {
if k8serrors.IsForbidden(err) {
log.Warnf("forbidden - failed to get %v service in %v namespace, err: %v", svcName, svcNs, err)
return ips, nil
}
return ips, err
}
for k, v := range svc.Spec.Selector {
pods, err := clients.KubeClient.CoreV1().Pods(svcNs).List(context.Background(), v1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", k, v)})
if err != nil {
return ips, err
}
for _, p := range pods.Items {
ips = append(ips, p.Status.PodIP)
}
}
return ips, nil
}

// getIpsForTargetHosts resolves IP addresses for comma-separated list of target hosts and returns comma-separated ips
func getIpsForTargetHosts(targetHosts string) (string, error) {
func getIpsForTargetHosts(targetHosts string, clients clients.ClientSets, serviceMesh bool) (string, error) {
if targetHosts == "" {
return "", nil
}
hosts := strings.Split(targetHosts, ",")
finalHosts := ""
var commaSeparatedIPs []string
for i := range hosts {
if strings.Contains(hosts[i], "svc.cluster.local") && serviceMesh {
ips, err := getPodIPFromService(hosts[i], clients)
if err != nil {
return "", err
}
commaSeparatedIPs = append(commaSeparatedIPs, ips...)
continue
}
ips, err := net.LookupIP(hosts[i])
if err != nil {
log.Warnf("Unknown host: {%v}, it won't be included in the scope of chaos", hosts[i])
Expand Down Expand Up @@ -404,3 +449,13 @@ func SetChaosTunables(experimentsDetails *experimentTypes.ExperimentDetails) {
experimentsDetails.PodsAffectedPerc = common.ValidateRange(experimentsDetails.PodsAffectedPerc)
experimentsDetails.Sequence = common.GetRandomSequence(experimentsDetails.Sequence)
}

// It checks if pod contains service mesh sidecar
func isServiceMeshEnabledForPod(pod apiv1.Pod) bool {
for _, c := range pod.Spec.Containers {
if common.StringExistsInSlice(c.Name, serviceMesh) {
return true
}
}
return false
}
3 changes: 2 additions & 1 deletion chaoslib/litmus/pod-network-partition/lib/network-policy.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lib

import (
"github.com/litmuschaos/litmus-go/pkg/clients"
"strings"

network_chaos "github.com/litmuschaos/litmus-go/chaoslib/litmus/network-chaos/lib"
Expand Down Expand Up @@ -179,7 +180,7 @@ func getPort(port int32, protocol corev1.Protocol) networkv1.NetworkPolicyPort {
// for which traffic should be blocked
func (np *NetworkPolicy) setExceptIPs(experimentsDetails *experimentTypes.ExperimentDetails) error {
// get all the target ips
destinationIPs, err := network_chaos.GetTargetIps(experimentsDetails.DestinationIPs, experimentsDetails.DestinationHosts)
destinationIPs, err := network_chaos.GetTargetIps(experimentsDetails.DestinationIPs, experimentsDetails.DestinationHosts, clients.ClientSets{}, false)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion chaoslib/pumba/network-chaos/lib/network-chaos.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func createHelperPod(experimentsDetails *experimentTypes.ExperimentDetails, clie
// AddTargetIpsArgs inserts a comma-separated list of targetIPs (if provided by the user) into the pumba command/args
func AddTargetIpsArgs(targetIPs, targetHosts string, args []string) ([]string, error) {

targetIPs, err := network_chaos.GetTargetIps(targetIPs, targetHosts)
targetIPs, err := network_chaos.GetTargetIps(targetIPs, targetHosts, clients.ClientSets{}, false)
if err != nil {
return nil, err
}
Expand Down
10 changes: 10 additions & 0 deletions pkg/utils/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,13 @@ func getRandomValue(a, b int) int {
rand.Seed(time.Now().Unix())
return (a + rand.Intn(b-a+1))
}

// StringExistsInSlice checks the existence of element in slice
func StringExistsInSlice(val string, slice []string) bool {
for _, v := range slice {
if strings.Contains(val, v) {
return true
}
}
return false
}

0 comments on commit 392d166

Please sign in to comment.