Skip to content

Commit

Permalink
feat-add-network-policy-01 (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
aguzmans authored Feb 22, 2024
1 parent 7d389f3 commit d259228
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 24 deletions.
1 change: 1 addition & 0 deletions cli/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ func ValidateKubernetesObjects(objects []string) ([]string, []string) {
"clusterrole": {"clusterrole", "clusterroles"},
"clusterrolebinding": {"clusterrolebinding", "clusterrolebindings"},
"crd": {"crd", "crds", "customresourcedefinition", "customresourcedefinitions"},
"networkpolicy": {"networkpolicy", "networkpolicies"},
// Add more valid objects and their aliases as needed
}

Expand Down
4 changes: 4 additions & 0 deletions compare/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ var typeAssertions = map[string]TypeAssertionFunc{
val, ok := obj.(*RbacV1.ClusterRoleBindingList)
return ok, val
},
"*networkingv1.NetworkPolicyList": func(obj interface{}) (bool, interface{}) {
val, ok := obj.(*networkingv1.NetworkPolicyList)
return ok, val
},
}

func GetTypeInfo(obj interface{}) (string, interface{}) {
Expand Down
32 changes: 32 additions & 0 deletions compare/networkpolicy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package compare

import (
"fmt"
"kompare/DAO"
"kompare/cli"
"kompare/query"
"kompare/tools"

"k8s.io/client-go/kubernetes"
)

func CompareNetworkPolicies(clientsetToSource, clientsetToTarget *kubernetes.Clientset, namespaceName string, TheArgs cli.ArgumentsReceivedValidated) ([]DAO.DiffWithName, error) {
var TheDiff []DAO.DiffWithName
sourceNetworkPolicies, err := query.ListNetworkPolicies(clientsetToSource, namespaceName)
if err != nil {
fmt.Printf("Error getting services list: %v\n", err)
return TheDiff, err
}
targetNetworkPolicies, err := query.ListNetworkPolicies(clientsetToTarget, namespaceName)
if err != nil {
fmt.Printf("Error getting services list: %v\n", err)
return TheDiff, err
}
var diffCriteria []string
if TheArgs.FiltersForObject == "" {
diffCriteria = []string{"Spec", "Name", "Annotations"}
} else {
diffCriteria = tools.ParseCommaSeparateList(TheArgs.FiltersForObject)
}
return CompareVerboseVSNonVerbose(sourceNetworkPolicies, targetNetworkPolicies, diffCriteria, TheArgs)
}
20 changes: 13 additions & 7 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ func main() {
// Connect to source cluster
clientsetToSource, err := connect.ConnectToSource(args.SourceClusterContext, &args.KubeconfigFile)
if err != nil {
err = fmt.Errorf("error connecting to source cluster: %v\n", err)
err = fmt.Errorf("error connecting to source cluster: %v", err)
panic(err)
}

// Connect to target cluster
clientsetToTarget, err := connect.ContextSwitch(args.TargetClusterContext, &args.KubeconfigFile)
if err != nil {
err = fmt.Errorf("error switching context: %v\n", err)
err = fmt.Errorf("error switching context: %v", err)
panic(err)
}

Expand Down Expand Up @@ -184,7 +184,7 @@ func iterateGoglabObjects(clientsetToSource, clientsetToTarget *kubernetes.Clien
func compareAllResourcesInNamespace(clientsetToSource, clientsetToTarget *kubernetes.Clientset, namespace string, TheArgs cli.ArgumentsReceivedValidated) {
fmt.Printf("Looping on Namespace: %s\n", namespace)
// Compare all resources for the namespace
resources := []string{"deployment", "ingress", "service", "serviceaccount", "configmap", "secret", "role", "rolebinding", "hpa", "cronjob"}
resources := []string{"deployment", "ingress", "service", "serviceaccount", "configmap", "secret", "role", "rolebinding", "hpa", "cronjob", "networkpolicy"}

// Create a title case converter for English
titleCase := cases.Title(language.English)
Expand All @@ -209,7 +209,7 @@ func compareResourcesByLists(clientsetToSource, clientsetToTarget *kubernetes.Cl
titleCase := cases.Title(language.English)

// Define all resources
allResources := []string{"deployment", "ingress", "service", "sa", "configmap", "secret", "role", "rolebinding"}
resources := []string{"deployment", "ingress", "service", "serviceaccout", "configmap", "secret", "role", "rolebinding", "networkpolicy", "hpa", "cronjob"}

// Compare resources based on include list
for _, resource := range includeResources {
Expand All @@ -222,7 +222,7 @@ func compareResourcesByLists(clientsetToSource, clientsetToTarget *kubernetes.Cl

// Compare resources based on exclude list
if excludeResources != nil {
for _, resource := range allResources {
for _, resource := range resources {
// Check if resource is not in the exclude list
if !tools.IsInList(resource, excludeResources) {
titleResource := titleCase.String(resource)
Expand Down Expand Up @@ -254,7 +254,7 @@ func compareResource(clientsetToSource, clientsetToTarget *kubernetes.Clientset,
err = fmt.Errorf("error comparing Services: %v", err)
panic(err)
}
case "sa":
case "serviceaccount":
_, err := compare.CompareServiceAccounts(clientsetToSource, clientsetToTarget, namespace, TheArgs)
if err != nil {
err = fmt.Errorf("error comparing Service Accounts: %v", err)
Expand Down Expand Up @@ -296,6 +296,12 @@ func compareResource(clientsetToSource, clientsetToTarget *kubernetes.Clientset,
err = fmt.Errorf("error comparing Cron Jobs: %v", err)
panic(err)
}
case "networkpolicy":
_, err := compare.CompareNetworkPolicies(clientsetToSource, clientsetToTarget, namespace, TheArgs)
if err != nil {
err = fmt.Errorf("error comparing Network Policies: %v", err)
panic(err)
}
}
}

Expand All @@ -308,7 +314,7 @@ func iterateNamespaces(sourceNameSpacesList *v1.NamespaceList, clientsetToSource
}
} else {
// Compare resources based on include or exclude lists
resources := []string{"deployment", "ingress", "service", "serviceaccount", "configmap", "secret", "role", "rolebinding", "hpa", "cronjob"}
resources := []string{"deployment", "ingress", "service", "serviceaccount", "configmap", "secret", "role", "rolebinding", "hpa", "cronjob", "networkpolicy"}
if tools.AreAnyInLists(TheArgs.Include, resources) || tools.AreAnyInLists(TheArgs.Exclude, resources) {
for _, ns := range sourceNameSpacesList.Items {
compareResourcesByLists(clientsetToSource, clientsetToTarget, ns.Name, TheArgs)
Expand Down
76 changes: 76 additions & 0 deletions mock/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func StartMockCluster() (string, *mux.Router, error) {
r.HandleFunc("/apis/rbac.authorization.k8s.io/v1/clusterroles", GetClusterRoles).Methods("GET")
r.HandleFunc("/apis/rbac.authorization.k8s.io/v1/clusterrolebindings", GetClusterRoleBindings).Methods("GET")
r.HandleFunc("/api/v1/namespaces/{namespace}/serviceaccounts", GetServiceAccounts).Methods("GET")
r.HandleFunc("/apis/networking.k8s.io/v1/namespaces/{namespace}/networkpolicies", GetNetworkPolicies).Methods("GET")

// Create a HTTP server instance
server := &http.Server{
Expand Down Expand Up @@ -720,6 +721,81 @@ func GetServices(w http.ResponseWriter, r *http.Request) {
}
}

func GetNetworkPolicies(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
namespace := vars["namespace"]

// Check if the namespace is "namespace2"
if namespace == "namespace2" {
// Create three sample network policies for namespace2
networkPolicies := &networkingv1.NetworkPolicyList{
ListMeta: metav1.ListMeta{
ResourceVersion: "320850103", // Set a sample resource version
},
Items: []networkingv1.NetworkPolicy{
{
ObjectMeta: metav1.ObjectMeta{
Name: "networkpolicy1",
Namespace: "namespace2",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "networkpolicy2",
Namespace: "namespace2",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "networkpolicy3",
Namespace: "namespace2",
},
},
},
}

// Convert the NetworkPolicyList object to JSON
jsonResponse, err := json.Marshal(networkPolicies)
if err != nil {
http.Error(w, "Error marshalling JSON response", http.StatusInternalServerError)
return
}

// Set the response headers and write the JSON response
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, err = w.Write(jsonResponse)
if err != nil {
http.Error(w, fmt.Sprintf("Error writing the JSON response: %v", err), http.StatusInternalServerError)
return
}
} else {
// If the namespace is not "namespace2", return an empty list of network policies
networkPolicies := &networkingv1.NetworkPolicyList{
ListMeta: metav1.ListMeta{
ResourceVersion: "0",
},
Items: []networkingv1.NetworkPolicy{},
}

// Convert the NetworkPolicyList object to JSON
jsonResponse, err := json.Marshal(networkPolicies)
if err != nil {
http.Error(w, "Error marshalling JSON response", http.StatusInternalServerError)
return
}

// Set the response headers and write the JSON response
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, err = w.Write(jsonResponse)
if err != nil {
http.Error(w, fmt.Sprintf("Error writing the JSON response: %v", err), http.StatusInternalServerError)
return
}
}
}

func SetupTestEnvironment() (string, string, *os.File) {
// Set up temporary kubeconfig file with mock cluster URLs
sourceClusterURL, _, _ := StartMockCluster()
Expand Down
43 changes: 26 additions & 17 deletions query/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ import (
func ListNameSpaces(clientset *kubernetes.Clientset) (*Corev1.NamespaceList, error) {
nsList, err := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the NameSpace List: %w", err)
return nil, fmt.Errorf("failed to query the NameSpace List: %w", err)
}
return nsList, nil
}

func GetNamespace(clientset *kubernetes.Clientset, name string) (*Corev1.Namespace, error) {
ns, err := clientset.CoreV1().Namespaces().Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the NameSpace Get: %w", err)
return nil, fmt.Errorf("failed to query the NameSpace Get: %w", err)
}
return ns, nil
}
Expand All @@ -55,7 +55,7 @@ func ListDeployments(clientset *kubernetes.Clientset, nameSpace string) (*v1.Dep
}
deployments_list, err := clientset.AppsV1().Deployments(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Deployment List: %w", err)
return nil, fmt.Errorf("failed to query the Deployment List: %w", err)
}
return deployments_list, nil
}
Expand All @@ -72,7 +72,7 @@ func ListHPAs(clientset *kubernetes.Clientset, nameSpace string) (*autoscalingv1
}
listHPA, err := clientset.AutoscalingV1().HorizontalPodAutoscalers(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the HPA List: %w", err)
return nil, fmt.Errorf("failed to query the HPA List: %w", err)
}
return listHPA, nil
}
Expand All @@ -87,7 +87,7 @@ func ListHPAs(clientset *kubernetes.Clientset, nameSpace string) (*autoscalingv1
func ListCronJobs(clientset *kubernetes.Clientset, nameSpace string) (*batchv1.CronJobList, error) {
listCronJobs, err := clientset.BatchV1().CronJobs(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Cron Job List: %w", err)
return nil, fmt.Errorf("failed to query the Cron Job List: %w", err)
}
return listCronJobs, nil
}
Expand All @@ -102,16 +102,16 @@ func ListCronJobs(clientset *kubernetes.Clientset, nameSpace string) (*batchv1.C
func ListCRDs(ctx, kubeconfig string) (*apiextensionv1.CustomResourceDefinitionList, error) {
config, err := connect.BuildConfigWithContextFromFlags(ctx, kubeconfig)
if err != nil {
return nil, fmt.Errorf("Failed to create config for quering CRDs: %w", err)
return nil, fmt.Errorf("failed to create config for quering CRDs: %w", err)
}
kubeClient, err := apiextension.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("Failed to get clientset for quering CRDs: %w", err)
return nil, fmt.Errorf("failed to get clientset for quering CRDs: %w", err)
}

listCRDs, err := kubeClient.ApiextensionsV1().CustomResourceDefinitions().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the CRD List: %w", err)
return nil, fmt.Errorf("failed to query the CRD List: %w", err)
}
return listCRDs, nil
}
Expand All @@ -126,7 +126,7 @@ func ListCRDs(ctx, kubeconfig string) (*apiextensionv1.CustomResourceDefinitionL
func ListIngresses(clientset *kubernetes.Clientset, nameSpace string) (*networkingv1.IngressList, error) {
listIngress, err := clientset.NetworkingV1().Ingresses(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Ingress List: %w", err)
return nil, fmt.Errorf("failed to query the Ingress List: %w", err)
}
return listIngress, nil
}
Expand All @@ -141,7 +141,7 @@ func ListIngresses(clientset *kubernetes.Clientset, nameSpace string) (*networki
func ListServices(clientset *kubernetes.Clientset, nameSpace string) (*Corev1.ServiceList, error) {
listServices, err := clientset.CoreV1().Services(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Kubernetes Services List: %w", err)
return nil, fmt.Errorf("failed to query the Kubernetes Services List: %w", err)
}
return listServices, nil
}
Expand All @@ -150,7 +150,7 @@ func ListServices(clientset *kubernetes.Clientset, nameSpace string) (*Corev1.Se
func ListConfigMaps(clientset *kubernetes.Clientset, nameSpace string) (*Corev1.ConfigMapList, error) {
ListConfigMaps, err := clientset.CoreV1().ConfigMaps(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Config Map List: %w", err)
return nil, fmt.Errorf("failed to query the Config Map List: %w", err)
}
return ListConfigMaps, nil
}
Expand All @@ -159,7 +159,7 @@ func ListConfigMaps(clientset *kubernetes.Clientset, nameSpace string) (*Corev1.
func ListSecrets(clientset *kubernetes.Clientset, nameSpace string) (*Corev1.SecretList, error) {
ListSercrets, err := clientset.CoreV1().Secrets(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Secrets List: %w", err)
return nil, fmt.Errorf("failed to query the Secrets List: %w", err)
}
return ListSercrets, nil
}
Expand All @@ -168,7 +168,7 @@ func ListSecrets(clientset *kubernetes.Clientset, nameSpace string) (*Corev1.Sec
func ListServiceAccounts(clientset *kubernetes.Clientset, nameSpace string) (*Corev1.ServiceAccountList, error) {
ListServiceAccounts, err := clientset.CoreV1().ServiceAccounts(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Service Accounts List: %w", err)
return nil, fmt.Errorf("failed to query the Service Accounts List: %w", err)
}
return ListServiceAccounts, nil
}
Expand All @@ -177,7 +177,7 @@ func ListServiceAccounts(clientset *kubernetes.Clientset, nameSpace string) (*Co
func ListRoles(clientset *kubernetes.Clientset, nameSpace string) (*RbacV1.RoleList, error) {
Listroles, err := clientset.RbacV1().Roles(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Roles List: %w", err)
return nil, fmt.Errorf("failed to query the Roles List: %w", err)
}
return Listroles, nil
}
Expand All @@ -186,7 +186,7 @@ func ListRoles(clientset *kubernetes.Clientset, nameSpace string) (*RbacV1.RoleL
func ListRoleBindings(clientset *kubernetes.Clientset, nameSpace string) (*RbacV1.RoleBindingList, error) {
ListRoleBindings, err := clientset.RbacV1().RoleBindings(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Role bindings List: %w", err)
return nil, fmt.Errorf("failed to query the Role bindings List: %w", err)
}
return ListRoleBindings, nil
}
Expand All @@ -195,7 +195,7 @@ func ListRoleBindings(clientset *kubernetes.Clientset, nameSpace string) (*RbacV
func ListClusterRoles(clientset *kubernetes.Clientset) (*RbacV1.ClusterRoleList, error) {
ListClusterRoles, err := clientset.RbacV1().ClusterRoles().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Cluster Roles List: %w", err)
return nil, fmt.Errorf("failed to query the Cluster Roles List: %w", err)
}
return ListClusterRoles, nil
}
Expand All @@ -204,7 +204,16 @@ func ListClusterRoles(clientset *kubernetes.Clientset) (*RbacV1.ClusterRoleList,
func ListClusterRoleBindings(clientset *kubernetes.Clientset) (*RbacV1.ClusterRoleBindingList, error) {
ListClusterRoleBindings, err := clientset.RbacV1().ClusterRoleBindings().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("Failed to query the Cluster Role Bindings List: %w", err)
return nil, fmt.Errorf("failed to query the Cluster Role Bindings List: %w", err)
}
return ListClusterRoleBindings, nil
}

// ListNetworkPolicy retrieves a list of NetworkPolicies in the specified namespace.
func ListNetworkPolicies(clientset *kubernetes.Clientset, nameSpace string) (*networkingv1.NetworkPolicyList, error) {
listNetworkPolicy, err := clientset.NetworkingV1().NetworkPolicies(nameSpace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("failed to query the Network Policy List: %w", err)
}
return listNetworkPolicy, nil
}
Loading

0 comments on commit d259228

Please sign in to comment.