architecture.go (113 lines of code) (raw):
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package alzlib
import (
"fmt"
"slices"
"github.com/Azure/alzlib/internal/processor"
mapset "github.com/deckarep/golang-set/v2"
)
// Architecture represents an Azure architecture that has not been deployed.
// Do not create this struct directly, use NewArchitecture instead.
type Architecture struct {
name string
mgs map[string]*ArchitectureManagementGroup
alzlib *AlzLib
}
// NewArchitecture creates a new Architecture with the given name and AlzLib.
func NewArchitecture(name string, az *AlzLib) *Architecture {
return &Architecture{
name: name,
mgs: make(map[string]*ArchitectureManagementGroup),
alzlib: az,
}
}
// Name returns the name of the architecture.
func (a *Architecture) Name() string {
return a.name
}
// RootMgs returns the top level management groups of the architecture.
func (a *Architecture) RootMgs() (res []*ArchitectureManagementGroup) {
for _, mg := range a.mgs {
if mg.parent != nil {
continue
}
res = append(res, mg)
}
slices.SortFunc(res, func(a, b *ArchitectureManagementGroup) int {
if a.id < b.id {
return -1
}
if a.id > b.id {
return 1
}
return 0
})
return res
}
// ArchitectureManagementGroup represents a management group in an undeployed architecture.
type ArchitectureManagementGroup struct {
id string
displayName string
children mapset.Set[*ArchitectureManagementGroup]
parent *ArchitectureManagementGroup
exists bool
archetypes mapset.Set[*Archetype]
architecture *Architecture
}
func newArchitectureManagementGroup(id, displayName string, exists bool, arch *Architecture) *ArchitectureManagementGroup {
return &ArchitectureManagementGroup{
id: id,
displayName: displayName,
children: mapset.NewThreadUnsafeSet[*ArchitectureManagementGroup](),
exists: exists,
archetypes: mapset.NewThreadUnsafeSet[*Archetype](),
architecture: arch,
}
}
// Archetypes returns the archetypes assigned to the management group.
func (mg *ArchitectureManagementGroup) Archetypes() (res []*Archetype) {
for arch := range mg.archetypes.Iter() {
res = append(res, arch.copy())
}
slices.SortFunc(res, func(a, b *Archetype) int {
if a.name < b.name {
return -1
}
if a.name > b.name {
return 1
}
return 0
})
return
}
// Children returns the child management groups of the management group.
func (mg *ArchitectureManagementGroup) Children() (res []*ArchitectureManagementGroup) {
for child := range mg.children.Iter() {
res = append(res, child)
}
return res
}
// DisplayName returns the display name of the management group.
func (mg *ArchitectureManagementGroup) DisplayName() string {
return mg.displayName
}
// Id returns the id of the management group.
func (mg *ArchitectureManagementGroup) Id() string {
return mg.id
}
// Exists returns the exists value.
func (mg *ArchitectureManagementGroup) Exists() bool {
return mg.exists
}
func (a *Architecture) addMgFromProcessor(libMg processor.LibArchitectureManagementGroup, az *AlzLib) error {
if _, ok := a.mgs[libMg.Id]; ok {
return fmt.Errorf("Architecture.addMg: management group %s already exists", libMg.Id)
}
mg := newArchitectureManagementGroup(libMg.Id, libMg.DisplayName, libMg.Exists, a)
// check parent exists and create parent-child relationship
if libMg.ParentId != nil {
parent, ok := a.mgs[*libMg.ParentId]
if !ok {
return fmt.Errorf("Architecture.addMg: parent management group does not exist %s", *libMg.ParentId)
}
mg.parent = parent
mg.parent.children.Add(mg)
}
mg.archetypes = mapset.NewThreadUnsafeSet[*Archetype]()
for archName := range libMg.Archetypes.Iter() {
arch, ok := az.archetypes[archName]
if !ok {
return fmt.Errorf("Architecture.addMg: archetype not found adding archetype `%s` to management group `%s`", archName, libMg.Id)
}
mg.archetypes.Add(arch)
}
a.mgs[mg.id] = mg
return nil
}