diff --git a/api/v1beta1/firewallgroup_types.go b/api/v1beta1/firewallgroup_types.go index ee7e36f..c662578 100644 --- a/api/v1beta1/firewallgroup_types.go +++ b/api/v1beta1/firewallgroup_types.go @@ -29,22 +29,22 @@ type FirewallGroupSpec struct { // Important: Run "make" to regenerate code after modifying this file // Foo is an example field of FirewallGroup. Edit firewallgroup_types.go to remove/update - // Description is a human-readable explanation for the object - Name string `json:"name,omitempty"` - - MatchServicesInAllNamespaces bool `json:"matchServicesInAllNamespaces,omitempty"` - // ManualAddresses is a list of manual IPs or CIDRs (IPv4 or IPv6) - // +optional - ManualAddresses []string `json:"manualAddresses,omitempty"` + // Description is a human-readable explanation for the object + Name string `json:"name,omitempty"` - // AutoIncludeSelector defines which services to extract addresses from - // +optional - AutoIncludeSelector *metav1.LabelSelector `json:"autoIncludeSelector,omitempty"` + MatchServicesInAllNamespaces bool `json:"matchServicesInAllNamespaces,omitempty"` + // ManualAddresses is a list of manual IPs or CIDRs (IPv4 or IPv6) + // +optional + ManualAddresses []string `json:"manualAddresses,omitempty"` - // AddressType can be "ip", "cidr", or "both" - // +kubebuilder:validation:Enum=ip;cidr;both - // +optional - AddressType string `json:"addressType,omitempty"` + // AutoIncludeSelector defines which services to extract addresses from + // +optional + AutoIncludeSelector *metav1.LabelSelector `json:"autoIncludeSelector,omitempty"` + + // AddressType can be "ip", "cidr", or "both" + // +kubebuilder:validation:Enum=ip;cidr;both + // +optional + AddressType string `json:"addressType,omitempty"` } // FirewallGroupStatus defines the observed state of FirewallGroup. @@ -52,15 +52,15 @@ type FirewallGroupStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file - ResolvedAddresses []string `json:"resolvedAddresses,omitempty"` + ResolvedAddresses []string `json:"resolvedAddresses,omitempty"` - // SyncedWithUnifi indicates whether the addresses are successfully pushed - // +optional - SyncedWithUnifi bool `json:"syncedWithUnifi,omitempty"` + // SyncedWithUnifi indicates whether the addresses are successfully pushed + // +optional + SyncedWithUnifi bool `json:"syncedWithUnifi,omitempty"` - // LastSyncTime is the last time the object was synced - // +optional - LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"` + // LastSyncTime is the last time the object was synced + // +optional + LastSyncTime *metav1.Time `json:"lastSyncTime,omitempty"` } // +kubebuilder:object:root=true diff --git a/api/v1beta1/networkconfiguration_types.go b/api/v1beta1/networkconfiguration_types.go index d0096a7..adc5a51 100644 --- a/api/v1beta1/networkconfiguration_types.go +++ b/api/v1beta1/networkconfiguration_types.go @@ -29,31 +29,30 @@ type NetworkconfigurationSpec struct { // Important: Run "make" to regenerate code after modifying this file // Foo is an example field of Networkconfiguration. Edit networkconfiguration_types.go to remove/update - Enabled bool `json:"enabled,omitempty"` - FirewallZoneID string `json:"firewall_zone_id,omitempty"` - GatewayType string `json:"gateway_type,omitempty"` - IPSubnet string `json:"ip_subnet,omitempty"` - Ipv6InterfaceType string `json:"ipv6_interface_type,omitempty"` - Ipv6PdAutoPrefixidEnabled bool `json:"ipv6_pd_auto_prefixid_enabled,omitempty"` - Ipv6RaEnabled bool `json:"ipv6_ra_enabled,omitempty"` - Ipv6SettingPreference string `json:"ipv6_setting_preference,omitempty"` - Ipv6Subnet string `json:"ipv6_subnet,omitempty"` - Name string `json:"name"` - Networkname string `json:"network_name"` - NetworkID string `json:"network_id,omitempty"` - Networkgroup string `json:"networkgroup,omitempty"` - Purpose string `json:"purpose,omitempty"` - SettingPreference string `json:"setting_preference,omitempty"` - Vlan int64 `json:"vlan,omitempty"` - VlanEnabled bool `json:"vlan_enabled,omitempty"` - + Enabled bool `json:"enabled,omitempty"` + FirewallZoneID string `json:"firewall_zone_id,omitempty"` + GatewayType string `json:"gateway_type,omitempty"` + IPSubnet string `json:"ip_subnet,omitempty"` + Ipv6InterfaceType string `json:"ipv6_interface_type,omitempty"` + Ipv6PdAutoPrefixidEnabled bool `json:"ipv6_pd_auto_prefixid_enabled,omitempty"` + Ipv6RaEnabled bool `json:"ipv6_ra_enabled,omitempty"` + Ipv6SettingPreference string `json:"ipv6_setting_preference,omitempty"` + Ipv6Subnet string `json:"ipv6_subnet,omitempty"` + Name string `json:"name"` + Networkname string `json:"network_name"` + NetworkID string `json:"network_id,omitempty"` + Networkgroup string `json:"networkgroup,omitempty"` + Purpose string `json:"purpose,omitempty"` + SettingPreference string `json:"setting_preference,omitempty"` + Vlan int64 `json:"vlan,omitempty"` + VlanEnabled bool `json:"vlan_enabled,omitempty"` } // NetworkconfigurationStatus defines the observed state of Networkconfiguration. type NetworkconfigurationStatus struct { // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster // Important: Run "make" to regenerate code after modifying this file - Ipv6SubnetStatus string `json:"ipv6_subnet_status,omitempty"` + Ipv6SubnetStatus string `json:"ipv6_subnet_status,omitempty"` } // +kubebuilder:object:root=true diff --git a/internal/controller/firewallgroup_controller.go b/internal/controller/firewallgroup_controller.go index aea91af..b194c06 100644 --- a/internal/controller/firewallgroup_controller.go +++ b/internal/controller/firewallgroup_controller.go @@ -18,8 +18,8 @@ package controller import ( "context" - "net" "fmt" + "net" "reflect" "k8s.io/apimachinery/pkg/runtime" @@ -27,15 +27,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" - unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" goUnifi "github.com/vegardengen/go-unifi/unifi" + unifiv1beta1 "github.com/vegardengen/unifi-network-operator/api/v1beta1" "github.com/vegardengen/unifi-network-operator/internal/unifi" ) // FirewallGroupReconciler reconciles a FirewallGroup object type FirewallGroupReconciler struct { client.Client - Scheme *runtime.Scheme + Scheme *runtime.Scheme UnifiClient *unifi.UnifiClient } @@ -53,125 +53,123 @@ type FirewallGroupReconciler struct { // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.20.2/pkg/reconcile - - func (r *FirewallGroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) var nwObj unifiv1beta1.FirewallGroup - if err := r.Get(ctx, req.NamespacedName, &nwObj); err != nil { - return ctrl.Result{}, client.IgnoreNotFound(err) - } + if err := r.Get(ctx, req.NamespacedName, &nwObj); err != nil { + return ctrl.Result{}, client.IgnoreNotFound(err) + } log.Info(nwObj.Spec.Name) var ipv4, ipv6 []string - - for _,addressEntry := range nwObj.Spec.ManualAddresses { - ip := net.ParseIP(addressEntry) - if ip != nil { - if ip.To4() != nil { - log.Info(fmt.Sprintf("IPv4 address: %s", addressEntry)) - ipv4 = append(ipv4, addressEntry) - } else { - log.Info(fmt.Sprintf("IPv6 address: %s", addressEntry)) - ipv6 = append(ipv6, ip.String()) - } - } else { - addr, net, err := net.ParseCIDR(addressEntry) - if err == nil && addr.Equal(net.IP) { - if addr.To4() != nil { - log.Info(fmt.Sprintf("Ipv4 Net: %s", net)) - ipv4 = append(ipv4, addressEntry) - } else { - mask,_ := net.Mask.Size() - log.Info(fmt.Sprintf("Ipv6 Net: %s", net)) - ipv6 = append(ipv6, addr.Mask(net.Mask).String() + "/" + fmt.Sprint(mask)) - } - } else { - log.Error(err,fmt.Sprintf("Could not parse: %s", addressEntry)) - return ctrl.Result{}, err - } - } - } - firewall_groups, err := r.UnifiClient.Client.ListFirewallGroup(context.Background(), r.UnifiClient.SiteID) - if err != nil { - log.Error(err,"Could not list network objects") - return ctrl.Result{}, err + for _, addressEntry := range nwObj.Spec.ManualAddresses { + ip := net.ParseIP(addressEntry) + + if ip != nil { + if ip.To4() != nil { + log.Info(fmt.Sprintf("IPv4 address: %s", addressEntry)) + ipv4 = append(ipv4, addressEntry) + } else { + log.Info(fmt.Sprintf("IPv6 address: %s", addressEntry)) + ipv6 = append(ipv6, ip.String()) + } + } else { + addr, net, err := net.ParseCIDR(addressEntry) + if err == nil && addr.Equal(net.IP) { + if addr.To4() != nil { + log.Info(fmt.Sprintf("Ipv4 Net: %s", net)) + ipv4 = append(ipv4, addressEntry) + } else { + mask, _ := net.Mask.Size() + log.Info(fmt.Sprintf("Ipv6 Net: %s", net)) + ipv6 = append(ipv6, addr.Mask(net.Mask).String()+"/"+fmt.Sprint(mask)) + } + } else { + log.Error(err, fmt.Sprintf("Could not parse: %s", addressEntry)) + return ctrl.Result{}, err + } + } } - ipv4_name := "k8s-"+nwObj.Spec.Name+"-ipv4" - ipv6_name := "k8s-"+nwObj.Spec.Name+"-ipv6" + firewall_groups, err := r.UnifiClient.Client.ListFirewallGroup(context.Background(), r.UnifiClient.SiteID) + if err != nil { + log.Error(err, "Could not list network objects") + return ctrl.Result{}, err + } + ipv4_name := "k8s-" + nwObj.Spec.Name + "-ipv4" + ipv6_name := "k8s-" + nwObj.Spec.Name + "-ipv6" ipv4_done := false ipv6_done := false - for _,firewall_group := range firewall_groups { - if firewall_group.Name == ipv4_name { - if(len(ipv4) == 0) { - log.Info(fmt.Sprintf("Delete %s", ipv4_name)) - err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) - if err != nil { - log.Error(err,"Could not delete firewall group") - return ctrl.Result{}, err - } - ipv4_done = true - } else { - if !reflect.DeepEqual(firewall_group.GroupMembers, ipv4) { - firewall_group.GroupMembers = ipv4 - log.Info(fmt.Sprintf("Updating %s", ipv4_name)) - _, err := r.UnifiClient.Client.UpdateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) - if err != nil { - log.Error(err,"Could not update firewall group") - return ctrl.Result{}, err - } - } - ipv4_done = true - } - } - if firewall_group.Name == ipv6_name { - if(len(ipv6) == 0) { - log.Info(fmt.Sprintf("Delete %s", ipv6_name)) - err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) - if err != nil { - log.Error(err,"Could not delete firewall group") - return ctrl.Result{}, err - } - ipv6_done = true - } else { - if !reflect.DeepEqual(firewall_group.GroupMembers, ipv6) { - firewall_group.GroupMembers = ipv6 - log.Info(fmt.Sprintf("Updating %s", ipv6_name)) - _, err := r.UnifiClient.Client.UpdateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) - if err != nil { - log.Error(err,"Could not update firewall group") - return ctrl.Result{}, err - } - } - ipv6_done = true - } - } + for _, firewall_group := range firewall_groups { + if firewall_group.Name == ipv4_name { + if len(ipv4) == 0 { + log.Info(fmt.Sprintf("Delete %s", ipv4_name)) + err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) + if err != nil { + log.Error(err, "Could not delete firewall group") + return ctrl.Result{}, err + } + ipv4_done = true + } else { + if !reflect.DeepEqual(firewall_group.GroupMembers, ipv4) { + firewall_group.GroupMembers = ipv4 + log.Info(fmt.Sprintf("Updating %s", ipv4_name)) + _, err := r.UnifiClient.Client.UpdateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) + if err != nil { + log.Error(err, "Could not update firewall group") + return ctrl.Result{}, err + } + } + ipv4_done = true + } + } + if firewall_group.Name == ipv6_name { + if len(ipv6) == 0 { + log.Info(fmt.Sprintf("Delete %s", ipv6_name)) + err := r.UnifiClient.Client.DeleteFirewallGroup(context.Background(), r.UnifiClient.SiteID, firewall_group.ID) + if err != nil { + log.Error(err, "Could not delete firewall group") + return ctrl.Result{}, err + } + ipv6_done = true + } else { + if !reflect.DeepEqual(firewall_group.GroupMembers, ipv6) { + firewall_group.GroupMembers = ipv6 + log.Info(fmt.Sprintf("Updating %s", ipv6_name)) + _, err := r.UnifiClient.Client.UpdateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) + if err != nil { + log.Error(err, "Could not update firewall group") + return ctrl.Result{}, err + } + } + ipv6_done = true + } + } } if len(ipv4) > 0 && !ipv4_done { - log.Info(fmt.Sprintf("Creating %s", ipv4_name)) - var firewall_group goUnifi.FirewallGroup - firewall_group.Name=ipv4_name - firewall_group.SiteID=r.UnifiClient.SiteID - firewall_group.GroupMembers = ipv4 - firewall_group.GroupType = "address-group" - _, err := r.UnifiClient.Client.CreateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) - if err != nil { - log.Error(err,"Could not create firewall group") - return ctrl.Result{}, err - } + log.Info(fmt.Sprintf("Creating %s", ipv4_name)) + var firewall_group goUnifi.FirewallGroup + firewall_group.Name = ipv4_name + firewall_group.SiteID = r.UnifiClient.SiteID + firewall_group.GroupMembers = ipv4 + firewall_group.GroupType = "address-group" + _, err := r.UnifiClient.Client.CreateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) + if err != nil { + log.Error(err, "Could not create firewall group") + return ctrl.Result{}, err + } } if len(ipv6) > 0 && !ipv6_done { - log.Info(fmt.Sprintf("Creating %s", ipv6_name)) - var firewall_group goUnifi.FirewallGroup - firewall_group.Name=ipv6_name - firewall_group.SiteID=r.UnifiClient.SiteID - firewall_group.GroupMembers = ipv6 - firewall_group.GroupType = "ipv6-address-group" - _, err := r.UnifiClient.Client.CreateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) - if err != nil { - log.Error(err,"Could not create firewall group") - return ctrl.Result{}, err - } + log.Info(fmt.Sprintf("Creating %s", ipv6_name)) + var firewall_group goUnifi.FirewallGroup + firewall_group.Name = ipv6_name + firewall_group.SiteID = r.UnifiClient.SiteID + firewall_group.GroupMembers = ipv6 + firewall_group.GroupType = "ipv6-address-group" + _, err := r.UnifiClient.Client.CreateFirewallGroup(context.Background(), r.UnifiClient.SiteID, &firewall_group) + if err != nil { + log.Error(err, "Could not create firewall group") + return ctrl.Result{}, err + } } return ctrl.Result{}, nil diff --git a/internal/controller/networkconfiguration_controller.go b/internal/controller/networkconfiguration_controller.go index a5033bf..ee375d0 100644 --- a/internal/controller/networkconfiguration_controller.go +++ b/internal/controller/networkconfiguration_controller.go @@ -32,7 +32,7 @@ import ( // NetworkconfigurationReconciler reconciles a Networkconfiguration object type NetworkconfigurationReconciler struct { client.Client - Scheme *runtime.Scheme + Scheme *runtime.Scheme UnifiClient *unifi.UnifiClient } @@ -53,35 +53,33 @@ func (r *NetworkconfigurationReconciler) Reconcile(ctx context.Context, req ctrl log := log.FromContext(ctx) var networkCRDs unifiv1.NetworkconfigurationList - if err := r.List(ctx, &networkCRDs); err != nil { - return ctrl.Result{}, err - } + if err := r.List(ctx, &networkCRDs); err != nil { + return ctrl.Result{}, err + } k8sNetworks := make(map[string]*unifiv1.Networkconfiguration) for i := range networkCRDs.Items { log.Info(fmt.Sprintf("Inserting network %s\n", networkCRDs.Items[i].Spec.NetworkID)) k8sNetworks[networkCRDs.Items[i].Spec.NetworkID] = &networkCRDs.Items[i] } - - networks, err := r.UnifiClient.Client.ListNetwork(context.Background(), r.UnifiClient.SiteID) if err != nil { - log.Error(err,"Failed to list Unifi Networks") - return ctrl.Result{}, err - } + log.Error(err, "Failed to list Unifi Networks") + return ctrl.Result{}, err + } seenNetworks := map[string]bool{} - for _,network := range networks { - networkID := network.ID - seenNetworks[networkID] = true - log.Info(fmt.Sprintf("Searching for %s\n",networkID)) + for _, network := range networks { + networkID := network.ID + seenNetworks[networkID] = true + log.Info(fmt.Sprintf("Searching for %s\n", networkID)) - if existing, found := k8sNetworks[networkID]; found { - log.Info(fmt.Sprintf("Found network match: %s/%s", existing.Spec.NetworkID,networkID)) - } else { - log.Info(fmt.Sprintf("New network: %s with ID %s", network.Name, network.ID)) - } + if existing, found := k8sNetworks[networkID]; found { + log.Info(fmt.Sprintf("Found network match: %s/%s", existing.Spec.NetworkID, networkID)) + } else { + log.Info(fmt.Sprintf("New network: %s with ID %s", network.Name, network.ID)) + } } return ctrl.Result{}, nil