package main import ( "io" "os" ) type Generator interface { Init(write io.Writer) error GenerateNamespace(writer io.Writer, namespace *Namespace) error GenerateCommunicationRule(writer io.Writer, app *Application, ingress *Ingress, egress *Egress) error } type ApplicationPeer struct { Application *Application Ports []Port Rule string } type NetworkPeer struct { Network *Network Ports []Port Rule string } type Peer struct { Applications []*ApplicationPeer Networks []*NetworkPeer Predefined []string } func (p *Peer) append(app *ApplicationPeer, network *NetworkPeer, predefined string) { if app != nil { p.Applications = append(p.Applications, app) } if network != nil { p.Networks = append(p.Networks, network) } if predefined != "" { p.Predefined = append(p.Predefined, predefined) } } func (p *Peer) Empty() bool { return len(p.Applications)+len(p.Networks)+len(p.Predefined) == 0 } func (p Peer) String() string { res := "" for _, app := range p.Applications { res += "app:" + app.Application.Name + " " } for _, net := range p.Networks { res += "net:" + net.Network.Name + " " } for _, pre := range p.Predefined { res += "pre:" + pre + " " } return res } type Ingress struct { Peer } type Egress struct { Peer } func Generate(writer io.Writer, generator Generator, config *Config) error { err := generator.Init(writer) if err != nil { return err } for _, ns := range config.Namespaces { err = generator.GenerateNamespace(os.Stdout, ns) if err != nil { return err } } // Loop over all applications and gather the ingress and egress for each application var ingresses = make(map[string]*Ingress) var egresses = make(map[string]*Egress) for _, ns := range config.Namespaces { for _, app := range ns.Applications { if ingresses[app.Name] == nil { ingresses[app.Name] = &Ingress{} } if egresses[app.Name] == nil { egresses[app.Name] = &Egress{} } } } for _, communication := range config.Communications { for _, from := range communication.From { appFrom, networkFrom, predefinedFrom := config.GetApplication(from) for _, to := range communication.To { appTo, networkTo, predefinedTo := config.GetApplication(to) if appFrom != nil { // we have an egress from appFrom egress := egresses[from] ports := communication.Ports var appPeer *ApplicationPeer = nil var networkPeer *NetworkPeer = nil if appTo != nil { if len(ports) == 0 { ports = appTo.Ports } appPeer = &ApplicationPeer{ Application: appTo, Ports: ports, Rule: "to", } } else if networkTo != nil { if len(ports) == 0 { ports = networkTo.Ports } networkPeer = &NetworkPeer{ Network: networkTo, Ports: ports, Rule: "to", } } egress.append(appPeer, networkPeer, predefinedTo) } if appTo != nil { // we have an ingress on appTo ingress := ingresses[to] ports := communication.Ports var appPeer *ApplicationPeer = nil var networkPeer *NetworkPeer = nil if appFrom != nil { if len(ports) == 0 { ports = appTo.Ports } appPeer = &ApplicationPeer{ Application: appFrom, Ports: ports, Rule: "from", } } else if networkFrom != nil { if len(ports) == 0 { ports = appTo.Ports } networkPeer = &NetworkPeer{ Network: networkFrom, Ports: ports, Rule: "from", } } ingress.append(appPeer, networkPeer, predefinedFrom) } } } } // loop over all apps and configure them for _, ns := range config.Namespaces { for _, app := range ns.Applications { ingress := ingresses[app.Name] egress := egresses[app.Name] if !ingress.Empty() || !egress.Empty() { err := generator.GenerateCommunicationRule(writer, app, ingress, egress) if err != nil { return err } } } } return nil }