Skip to content

Commit

Permalink
chore: fix version and allow new -A and --all behaviour
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Fornaro <[email protected]>
  • Loading branch information
xunholy committed Nov 13, 2023
1 parent 97a8ec7 commit 86ac8a9
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 33 deletions.
2 changes: 1 addition & 1 deletion .slsa-goreleaser/darwin-amd64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ ldflags:
- "-X main.Commit={{ .Env.COMMIT }}"
- "-X main.CommitDate={{ .Env.COMMIT_DATE }}"
- "-X main.TreeState={{ .Env.TREE_STATE }}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version=${VERSION}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version={{ .Env.VERSION }}"
2 changes: 1 addition & 1 deletion .slsa-goreleaser/darwin-arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ ldflags:
- "-X main.Commit={{ .Env.COMMIT }}"
- "-X main.CommitDate={{ .Env.COMMIT_DATE }}"
- "-X main.TreeState={{ .Env.TREE_STATE }}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version=${VERSION}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version={{ .Env.VERSION }}"
2 changes: 1 addition & 1 deletion .slsa-goreleaser/linux-amd64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ ldflags:
- "-X main.Commit={{ .Env.COMMIT }}"
- "-X main.CommitDate={{ .Env.COMMIT_DATE }}"
- "-X main.TreeState={{ .Env.TREE_STATE }}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version=${VERSION}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version={{ .Env.VERSION }}"
2 changes: 1 addition & 1 deletion .slsa-goreleaser/linux-arm64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ ldflags:
- "-X main.Commit={{ .Env.COMMIT }}"
- "-X main.CommitDate={{ .Env.COMMIT_DATE }}"
- "-X main.TreeState={{ .Env.TREE_STATE }}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version=${VERSION}"
- "-X github.com/xentra-ai/advisor/pkg/k8s.Version={{ .Env.VERSION }}"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Contributions are welcome! Please read the contributing guide to get started.

## 📄 License

This project is licensed under the [PLACEHOLDER] License - see the [LICENSE.md](LICENSE.md) file for details.
This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.

## 🙏 Acknowledgments

Expand Down
40 changes: 36 additions & 4 deletions advisor/cmd/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,50 @@ var genCmd = &cobra.Command{
Short: "Generate resources",
}

var (
allNamespaces bool
allInNamespace bool
)

func init() {
networkPolicyCmd.Flags().BoolVarP(&allNamespaces, "all-namespaces", "A", false, "Generate policies for all pods in all namespaces")
networkPolicyCmd.Flags().BoolVar(&allInNamespace, "all", false, "Generate policies for all pods in the current namespace")
}

var networkPolicyCmd = &cobra.Command{
Use: "networkpolicy [pod-name]",
Aliases: []string{"netpol"},
Short: "Generate network policy",
Args: cobra.ExactArgs(1),
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
// Retrieve the config from the command context
config, ok := cmd.Context().Value(k8s.ConfigKey).(*k8s.Config)
if !ok {
log.Fatal().Msg("Failed to retrieve Kubernetes configuration")
}
podName := args[0]

// Get the namespace from kubeConfigFlags
namespace, _, err := kubeConfigFlags.ToRawKubeConfigLoader().Namespace()
if err != nil {
log.Fatal().Err(err).Msg("Failed to get namespace")
}

options := k8s.GenerateOptions{}

if allNamespaces {
options.Mode = k8s.AllPodsInAllNamespaces
} else if allInNamespace {
options.Mode = k8s.AllPodsInNamespace
options.Namespace = namespace
} else {
// Validate that a pod name is provided
if len(args) != 1 {
cmd.Usage()

Check failure on line 51 in advisor/cmd/gen.go

View workflow job for this annotation

GitHub Actions / lint (1.21.x)

Error return value of `cmd.Usage` is not checked (errcheck)
return
}
options.Mode = k8s.SinglePod
options.PodName = args[0]
options.Namespace = namespace
}

stopChan, errChan, done := k8s.PortForward(config)
<-done // Block until we receive a notification from the goroutine that port-forwarding has been set up
Expand All @@ -32,7 +64,7 @@ var networkPolicyCmd = &cobra.Command{
}
}()
log.Debug().Msg("Port forwarding set up successfully.")
k8s.GenerateNetworkPolicy(podName, config)
k8s.GenerateNetworkPolicy(options, config)
close(stopChan)
},
}
4 changes: 2 additions & 2 deletions advisor/pkg/api/pod_traffic.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ func GetPodTraffic(podName string) ([]PodTraffic, error) {

// Parse the JSON response and unmarshal it into the Go struct.
if err := json.Unmarshal([]byte(body), &podTraffic); err != nil {
log.Error().Err(err).Msg("Error unmarshal JSON")
log.Warn().Err(err).Msg("Error unmarshal JSON")
return nil, err
}

// If no pod traffic is found, return nil
if len(podTraffic) == 0 {
log.Error().Err(err).Msg("No pod traffic found")
log.Warn().Err(err).Msg("No pod traffic found in database")
return nil, nil
}
return podTraffic, nil
Expand Down
129 changes: 107 additions & 22 deletions advisor/pkg/k8s/networkpolicies.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package k8s

import (
"context"
"encoding/json"
"strings"

log "github.com/rs/zerolog/log"
api "github.com/xentra-ai/advisor/pkg/api"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
Expand All @@ -15,6 +17,22 @@ import (
// Version is set at build time using -ldflags
var Version = "development" // default value

// ModeType defines the mode of operation for generating network policies
type ModeType int

const (
SinglePod ModeType = iota
AllPodsInNamespace
AllPodsInAllNamespaces
)

// GenerateOptions holds options for the GenerateNetworkPolicy function
type GenerateOptions struct {
Mode ModeType
PodName string // Used if Mode is SinglePod
Namespace string // Used if Mode is AllPodsInNamespace or SinglePod
}

type NetworkPolicyRule struct {
Ports []networkingv1.NetworkPolicyPort
FromTo []networkingv1.NetworkPolicyPeer
Expand All @@ -32,35 +50,72 @@ type RuleSets struct {
Egress []networkingv1.NetworkPolicyEgressRule
}

func GenerateNetworkPolicy(podName string, config *Config) {
podTraffic, err := api.GetPodTraffic(podName)
if err != nil {
log.Fatal().Err(err).Msg("Error retrieving pod traffic")
}
func GenerateNetworkPolicy(options GenerateOptions, config *Config) {
var pods []corev1.Pod

if podTraffic == nil {
log.Fatal().Msgf("No pod traffic found for pod %s\n", podName)
}
switch options.Mode {
case SinglePod:
// Fetch all pods in the given namespace
fetchedPod, err := fetchSinglePodInNamespace(options.PodName, options.Namespace, config)
if err != nil {
log.Fatal().Err(err).Msgf("failed to fetch pods in namespace %s", options.Namespace)
}
pods = append(pods, *fetchedPod)

podDetail, err := api.GetPodSpec(podTraffic[0].SrcIP)
if err != nil {
log.Fatal().Err(err).Msg("Error retrieving pod spec")
}
case AllPodsInNamespace:
// Fetch all pods in the given namespace
fetchedPods, err := fetchAllPodsInNamespace(options.Namespace, config)
if err != nil {
log.Fatal().Err(err).Msgf("failed to fetch pods in namespace %s", options.Namespace)
}
pods = append(pods, fetchedPods...)

if podDetail == nil {
log.Fatal().Msgf("No pod spec found for pod %s\n", podTraffic[0].SrcIP)
case AllPodsInAllNamespaces:
// Fetch all pods in all namespaces
fetchedPods, err := fetchAllPodsInAllNamespaces(config)
if err != nil {
log.Fatal().Err(err).Msgf("failed to fetch all pods in all namespaces")
}
pods = append(pods, fetchedPods...)
}

policy, err := transformToNetworkPolicy(podTraffic, podDetail, config)
if err != nil {
log.Error().Err(err).Msg("Error transforming policy")
}
// Generate network policies for each pod in pods
for _, pod := range pods {
podTraffic, err := api.GetPodTraffic(pod.Name)
if err != nil {
log.Error().Err(err).Msg("Error retrieving pod traffic")
continue
}

policyYAML, err := yaml.Marshal(policy)
if err != nil {
log.Error().Err(err).Msg("Error converting policy to YAML")
if podTraffic == nil {
log.Error().Msgf("No pod traffic found for pod %s\n", pod.Name)
continue
}

podDetail, err := api.GetPodSpec(podTraffic[0].SrcIP)
if err != nil {
log.Error().Err(err).Msg("Error retrieving pod spec")
continue
}

if podDetail == nil {
log.Error().Msgf("No pod spec found for pod %s\n", podTraffic[0].SrcIP)
continue
}

policy, err := transformToNetworkPolicy(podTraffic, podDetail, config)
if err != nil {
log.Error().Err(err).Msg("Error transforming policy")
continue
}

policyYAML, err := yaml.Marshal(policy)
if err != nil {
log.Error().Err(err).Msg("Error converting policy to YAML")
continue
}
log.Info().Msgf("Generated policy for pod %s:\n%s", pod.Name, string(policyYAML))
}
log.Info().Msgf("Generated policy for pod %s:\n%s", podName, string(policyYAML))
}

func transformToNetworkPolicy(podTraffic []api.PodTraffic, podDetail *api.PodDetail, config *Config) (*networkingv1.NetworkPolicy, error) {
Expand Down Expand Up @@ -242,3 +297,33 @@ func deduplicateEgressRules(rules []networkingv1.NetworkPolicyEgressRule) []netw
}
return deduplicated
}

// fetchSinglePodInNamespace fetches a single pods in a specific namespace
func fetchSinglePodInNamespace(podName, namespace string, config *Config) (*corev1.Pod, error) {
pod, err := config.Clientset.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
if err != nil {
// Handle the error according to your application's requirements
return nil, err
}
return pod, nil
}

// fetchAllPodsInNamespace fetches all pods in a specific namespace
func fetchAllPodsInNamespace(namespace string, config *Config) ([]corev1.Pod, error) {
podList, err := config.Clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}

return podList.Items, nil
}

// fetchAllPodsInAllNamespaces fetches all pods in all namespaces
func fetchAllPodsInAllNamespaces(config *Config) ([]corev1.Pod, error) {
podList, err := config.Clientset.CoreV1().Pods(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}

return podList.Items, nil
}

0 comments on commit 86ac8a9

Please sign in to comment.