Files
defiQUG 9daf1fd378 Apply Composer changes: comprehensive API updates, migrations, middleware, and infrastructure improvements
- Add comprehensive database migrations (001-024) for schema evolution
- Enhance API schema with expanded type definitions and resolvers
- Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth
- Implement new services: AI optimization, billing, blockchain, compliance, marketplace
- Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage)
- Update Crossplane provider with enhanced VM management capabilities
- Add comprehensive test suite for API endpoints and services
- Update frontend components with improved GraphQL subscriptions and real-time updates
- Enhance security configurations and headers (CSP, CORS, etc.)
- Update documentation and configuration files
- Add new CI/CD workflows and validation scripts
- Implement design system improvements and UI enhancements
2025-12-12 18:01:35 -08:00

222 lines
6.4 KiB
Go

package discovery
import (
"context"
"fmt"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// KubernetesDiscoveryAgent discovers Kubernetes resources
type KubernetesDiscoveryAgent struct {
client kubernetes.Interface
site string
region string
}
// NewKubernetesDiscoveryAgent creates a new Kubernetes discovery agent
func NewKubernetesDiscoveryAgent(client kubernetes.Interface, site, region string) *KubernetesDiscoveryAgent {
return &KubernetesDiscoveryAgent{
client: client,
site: site,
region: region,
}
}
// DiscoverNamespaces discovers all namespaces
func (a *KubernetesDiscoveryAgent) DiscoverNamespaces(ctx context.Context) ([]DiscoveredResource, error) {
namespaces, err := a.client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to list namespaces")
}
var resources []DiscoveredResource
for _, ns := range namespaces.Items {
resources = append(resources, DiscoveredResource{
ResourceType: "NAMESPACE",
Provider: "KUBERNETES",
ProviderID: fmt.Sprintf("namespace:%s", ns.Name),
Name: ns.Name,
Region: a.region,
SiteID: a.site,
Metadata: map[string]interface{}{
"uid": string(ns.UID),
"labels": ns.Labels,
"annotations": ns.Annotations,
"phase": string(ns.Status.Phase),
},
Tags: getTagsFromLabels(ns.Labels),
})
}
return resources, nil
}
// DiscoverDeployments discovers all deployments
func (a *KubernetesDiscoveryAgent) DiscoverDeployments(ctx context.Context) ([]DiscoveredResource, error) {
namespaces, err := a.client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to list namespaces")
}
var resources []DiscoveredResource
for _, ns := range namespaces.Items {
deployments, err := a.client.AppsV1().Deployments(ns.Name).List(ctx, metav1.ListOptions{})
if err != nil {
continue // Skip namespaces we can't access
}
for _, dep := range deployments.Items {
resources = append(resources, DiscoveredResource{
ResourceType: "DEPLOYMENT",
Provider: "KUBERNETES",
ProviderID: fmt.Sprintf("deployment:%s:%s", ns.Name, dep.Name),
Name: dep.Name,
Region: a.region,
SiteID: a.site,
Metadata: map[string]interface{}{
"namespace": ns.Name,
"uid": string(dep.UID),
"replicas": dep.Spec.Replicas,
"readyReplicas": dep.Status.ReadyReplicas,
"labels": dep.Labels,
"annotations": dep.Annotations,
},
Tags: getTagsFromLabels(dep.Labels),
})
}
}
return resources, nil
}
// DiscoverServices discovers all services
func (a *KubernetesDiscoveryAgent) DiscoverServices(ctx context.Context) ([]DiscoveredResource, error) {
namespaces, err := a.client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to list namespaces")
}
var resources []DiscoveredResource
for _, ns := range namespaces.Items {
services, err := a.client.CoreV1().Services(ns.Name).List(ctx, metav1.ListOptions{})
if err != nil {
continue
}
for _, svc := range services.Items {
resources = append(resources, DiscoveredResource{
ResourceType: "SERVICE",
Provider: "KUBERNETES",
ProviderID: fmt.Sprintf("service:%s:%s", ns.Name, svc.Name),
Name: svc.Name,
Region: a.region,
SiteID: a.site,
Metadata: map[string]interface{}{
"namespace": ns.Name,
"uid": string(svc.UID),
"type": string(svc.Spec.Type),
"clusterIP": svc.Spec.ClusterIP,
"ports": svc.Spec.Ports,
"labels": svc.Labels,
"annotations": svc.Annotations,
},
Tags: getTagsFromLabels(svc.Labels),
})
}
}
return resources, nil
}
// DiscoverIngress discovers all ingress resources
func (a *KubernetesDiscoveryAgent) DiscoverIngress(ctx context.Context) ([]DiscoveredResource, error) {
namespaces, err := a.client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to list namespaces")
}
var resources []DiscoveredResource
for _, ns := range namespaces.Items {
ingresses, err := a.client.NetworkingV1().Ingresses(ns.Name).List(ctx, metav1.ListOptions{})
if err != nil {
continue
}
for _, ing := range ingresses.Items {
resources = append(resources, DiscoveredResource{
ResourceType: "INGRESS",
Provider: "KUBERNETES",
ProviderID: fmt.Sprintf("ingress:%s:%s", ns.Name, ing.Name),
Name: ing.Name,
Region: a.region,
SiteID: a.site,
Metadata: map[string]interface{}{
"namespace": ns.Name,
"uid": string(ing.UID),
"hosts": ing.Spec.Rules,
"tls": ing.Spec.TLS,
"labels": ing.Labels,
"annotations": ing.Annotations,
},
Tags: getTagsFromLabels(ing.Labels),
})
}
}
return resources, nil
}
// DiscoverAll discovers all Kubernetes resources
func (a *KubernetesDiscoveryAgent) DiscoverAll(ctx context.Context) ([]DiscoveredResource, error) {
var allResources []DiscoveredResource
// Discover namespaces
namespaces, err := a.DiscoverNamespaces(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to discover namespaces")
}
allResources = append(allResources, namespaces...)
// Discover deployments
deployments, err := a.DiscoverDeployments(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to discover deployments")
}
allResources = append(allResources, deployments...)
// Discover services
services, err := a.DiscoverServices(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to discover services")
}
allResources = append(allResources, services...)
// Discover ingress
ingresses, err := a.DiscoverIngress(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to discover ingress")
}
allResources = append(allResources, ingresses...)
return allResources, nil
}
// getTagsFromLabels extracts tags from Kubernetes labels
func getTagsFromLabels(labels map[string]string) []string {
var tags []string
for key, value := range labels {
if key == "tags" || key == "tag" {
// If label value is comma-separated, split it
// Otherwise, use key=value format
tags = append(tags, value)
} else if key == "app" || key == "component" || key == "environment" {
tags = append(tags, fmt.Sprintf("%s:%s", key, value))
}
}
return tags
}