fix: resolve network-group attachments at deploy time
- deployAttachments now checks both domain-specific and network group configs - Added resolveAttachmentsForDomain() to collect attachments from all sources - Deduplicates images if configured at both domain and group level - Fixed broken doc links to removed docs/cli/commands.md
- commit
- 59d74ee5edeba0264cf54575475724d8a112f302
- author
- brice · · 2026-01-17 19:27 UTC
- parent
- 9d1b34a
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
3 files · +40 -4
M docs/config/attachments.md +1 -1
| @@ -274,4 +274,4 @@ gordon attach remove app.mydomain.com postgres:18 | |||
| 274 | 274 | - [Network Isolation](./network-isolation.md) | |
| 275 | 275 | - [Network Groups](./network-groups.md) | |
| 276 | 276 | - [Routes](./routes.md) | |
| 277 | - | - [CLI Commands](/docs/cli/commands.md) | |
| 277 | + | - [CLI Commands](/docs/cli/index.md) | |
| @@ -274,4 +274,4 @@ gordon attach remove app.mydomain.com postgres:18 | |||||
| 274 | - [Network Isolation](./network-isolation.md) | 274 | - [Network Isolation](./network-isolation.md) | ||
| 275 | - [Network Groups](./network-groups.md) | 275 | - [Network Groups](./network-groups.md) | ||
| 276 | - [Routes](./routes.md) | 276 | - [Routes](./routes.md) | ||
| 277 | - | - [CLI Commands](/docs/cli/commands.md) | 277 | + | - [CLI Commands](/docs/cli/index.md) |
M internal/usecase/container/service.go +38 -2
| @@ -937,8 +937,9 @@ func (s *Service) cleanupNetworkIfEmpty(ctx context.Context, networkName string) | |||
| 937 | 937 | } | |
| 938 | 938 | ||
| 939 | 939 | func (s *Service) deployAttachments(ctx context.Context, domainName, networkName string) error { | |
| 940 | - | attachments, ok := s.config.Attachments[domainName] | |
| 941 | - | if !ok { | |
| 940 | + | // Collect attachments from both domain-specific and network group configs | |
| 941 | + | attachments := s.resolveAttachmentsForDomain(domainName) | |
| 942 | + | if len(attachments) == 0 { | |
| 942 | 943 | return nil | |
| 943 | 944 | } | |
| 944 | 945 | ||
| @@ -952,6 +953,41 @@ func (s *Service) deployAttachments(ctx context.Context, domainName, networkName | |||
| 952 | 953 | return nil | |
| 953 | 954 | } | |
| 954 | 955 | ||
| 956 | + | // resolveAttachmentsForDomain returns attachments for a domain by checking: | |
| 957 | + | // 1. Direct domain attachments (attachments[domain]) | |
| 958 | + | // 2. Network group attachments (attachments[group] where domain is in network_groups[group]) | |
| 959 | + | func (s *Service) resolveAttachmentsForDomain(domainName string) []string { | |
| 960 | + | seen := make(map[string]bool) | |
| 961 | + | var result []string | |
| 962 | + | ||
| 963 | + | // First, add domain-specific attachments | |
| 964 | + | if domainAttachments, ok := s.config.Attachments[domainName]; ok { | |
| 965 | + | for _, img := range domainAttachments { | |
| 966 | + | if !seen[img] { | |
| 967 | + | seen[img] = true | |
| 968 | + | result = append(result, img) | |
| 969 | + | } | |
| 970 | + | } | |
| 971 | + | } | |
| 972 | + | ||
| 973 | + | // Then, find which network group this domain belongs to and add group attachments | |
| 974 | + | for groupName, domains := range s.config.NetworkGroups { | |
| 975 | + | if slices.Contains(domains, domainName) { | |
| 976 | + | if groupAttachments, ok := s.config.Attachments[groupName]; ok { | |
| 977 | + | for _, img := range groupAttachments { | |
| 978 | + | if !seen[img] { | |
| 979 | + | seen[img] = true | |
| 980 | + | result = append(result, img) | |
| 981 | + | } | |
| 982 | + | } | |
| 983 | + | } | |
| 984 | + | break // Domain can only be in one network group | |
| 985 | + | } | |
| 986 | + | } | |
| 987 | + | ||
| 988 | + | return result | |
| 989 | + | } | |
| 990 | + | ||
| 955 | 991 | func (s *Service) getAttachmentsForDomain(ctx context.Context, domainName string) []domain.Attachment { | |
| 956 | 992 | containers, err := s.runtime.ListContainers(ctx, true) | |
| 957 | 993 | if err != nil { | |
| @@ -937,8 +937,9 @@ func (s *Service) cleanupNetworkIfEmpty(ctx context.Context, networkName string) | |||||
| 937 | } | 937 | } | ||
| 938 | 938 | ||||
| 939 | func (s *Service) deployAttachments(ctx context.Context, domainName, networkName string) error { | 939 | func (s *Service) deployAttachments(ctx context.Context, domainName, networkName string) error { | ||
| 940 | - | attachments, ok := s.config.Attachments[domainName] | 940 | + | // Collect attachments from both domain-specific and network group configs |
| 941 | - | if !ok { | 941 | + | attachments := s.resolveAttachmentsForDomain(domainName) |
| 942 | + | if len(attachments) == 0 { | |||
| 942 | return nil | 943 | return nil | ||
| 943 | } | 944 | } | ||
| 944 | 945 | ||||
| @@ -952,6 +953,41 @@ func (s *Service) deployAttachments(ctx context.Context, domainName, networkName | |||||
| 952 | return nil | 953 | return nil | ||
| 953 | } | 954 | } | ||
| 954 | 955 | ||||
| 956 | + | // resolveAttachmentsForDomain returns attachments for a domain by checking: | |||
| 957 | + | // 1. Direct domain attachments (attachments[domain]) | |||
| 958 | + | // 2. Network group attachments (attachments[group] where domain is in network_groups[group]) | |||
| 959 | + | func (s *Service) resolveAttachmentsForDomain(domainName string) []string { | |||
| 960 | + | seen := make(map[string]bool) | |||
| 961 | + | var result []string | |||
| 962 | + | ||||
| 963 | + | // First, add domain-specific attachments | |||
| 964 | + | if domainAttachments, ok := s.config.Attachments[domainName]; ok { | |||
| 965 | + | for _, img := range domainAttachments { | |||
| 966 | + | if !seen[img] { | |||
| 967 | + | seen[img] = true | |||
| 968 | + | result = append(result, img) | |||
| 969 | + | } | |||
| 970 | + | } | |||
| 971 | + | } | |||
| 972 | + | ||||
| 973 | + | // Then, find which network group this domain belongs to and add group attachments | |||
| 974 | + | for groupName, domains := range s.config.NetworkGroups { | |||
| 975 | + | if slices.Contains(domains, domainName) { | |||
| 976 | + | if groupAttachments, ok := s.config.Attachments[groupName]; ok { | |||
| 977 | + | for _, img := range groupAttachments { | |||
| 978 | + | if !seen[img] { | |||
| 979 | + | seen[img] = true | |||
| 980 | + | result = append(result, img) | |||
| 981 | + | } | |||
| 982 | + | } | |||
| 983 | + | } | |||
| 984 | + | break // Domain can only be in one network group | |||
| 985 | + | } | |||
| 986 | + | } | |||
| 987 | + | ||||
| 988 | + | return result | |||
| 989 | + | } | |||
| 990 | + | ||||
| 955 | func (s *Service) getAttachmentsForDomain(ctx context.Context, domainName string) []domain.Attachment { | 991 | func (s *Service) getAttachmentsForDomain(ctx context.Context, domainName string) []domain.Attachment { | ||
| 956 | containers, err := s.runtime.ListContainers(ctx, true) | 992 | containers, err := s.runtime.ListContainers(ctx, true) | ||
| 957 | if err != nil { | 993 | if err != nil { | ||
M wiki/guides/remote-cli.md +1 -1
| @@ -435,6 +435,6 @@ See [Remote Logs Requirement](#remote-logs-requirement) for details. | |||
| 435 | 435 | ||
| 436 | 436 | ## Related | |
| 437 | 437 | ||
| 438 | - | - [CLI Commands](/docs/cli/commands.md) | |
| 438 | + | - [CLI Commands](/docs/cli/index.md) | |
| 439 | 439 | - [Authentication](/docs/config/auth.md) | |
| 440 | 440 | - [Attachments](/docs/config/attachments.md) | |
| @@ -435,6 +435,6 @@ See [Remote Logs Requirement](#remote-logs-requirement) for details. | |||||
| 435 | 435 | ||||
| 436 | ## Related | 436 | ## Related | ||
| 437 | 437 | ||||
| 438 | - | - [CLI Commands](/docs/cli/commands.md) | 438 | + | - [CLI Commands](/docs/cli/index.md) |
| 439 | - [Authentication](/docs/config/auth.md) | 439 | - [Authentication](/docs/config/auth.md) | ||
| 440 | - [Attachments](/docs/config/attachments.md) | 440 | - [Attachments](/docs/config/attachments.md) | ||