package main import ( "fmt" "io" "log" "os" ) type Generator interface { GenerateNamespace(writer io.Writer, namespace *Namespace) error GenerateCommunicationRule(writer io.Writer, app *Application, ingress *Ingress, egress *Egress) error } type Peer struct { Applications []*Application Networks []*Network Predefined []string } func (p *Peer) append(app *Application, network *Network, 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.Name + " " } for _, net := range p.Networks { res += "net:" + net.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 { log.Printf("CONFIG %+v", config) 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 applications = make(map[string]*Application) var ingresses = make(map[string]*Ingress) var egresses = make(map[string]*Egress) for _, ns := range config.Namespaces { for _, app := range ns.Applications { applications[app.Name] = app 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 egress := egresses[from] egress.append(appTo, networkTo, predefinedTo) } if appTo != nil { // we have an ingress ingress := ingresses[to] ingress.append(appFrom, networkFrom, predefinedFrom) } } } } // loop over all apps and configure them for app, ingress := range ingresses { egress := egresses[app] if !ingress.Empty() || !egress.Empty() { fmt.Fprintf(os.Stderr, "RULE %s\n", app) fmt.Fprintf(os.Stderr, " IN %s\n", ingress) fmt.Fprintf(os.Stderr, " OUT %s\n", egress) err := generator.GenerateCommunicationRule(writer, applications[app], ingress, egress) if err != nil { return err } } } return nil }