Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions cmd/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ var envCmd = &cobra.Command{
}
}

// Resolve config handler to check vm.driver
vmDriver := configHandler.GetString("vm.driver")

// Create virtualization and service components only if vm.driver is configured
if vmDriver != "" {
if err := controller.CreateVirtualizationComponents(); err != nil {
if verbose {
return fmt.Errorf("Error creating virtualization components: %w", err)
}
return nil
}

if err := controller.CreateServiceComponents(); err != nil {
if verbose {
return fmt.Errorf("Error creating service components: %w", err)
}
return nil
}
}

// Create environment components
if err := controller.CreateEnvComponents(); err != nil {
if verbose {
Expand Down Expand Up @@ -86,26 +106,6 @@ var envCmd = &cobra.Command{
return nil
}

// Resolve config handler to check vm.driver
vmDriver := configHandler.GetString("vm.driver")

// Create virtualization and service components only if vm.driver is configured
if vmDriver != "" {
if err := controller.CreateVirtualizationComponents(); err != nil {
if verbose {
return fmt.Errorf("Error creating virtualization components: %w", err)
}
return nil
}

if err := controller.CreateServiceComponents(); err != nil {
if verbose {
return fmt.Errorf("Error creating service components: %w", err)
}
return nil
}
}

// Check if --decrypt flag is set
decrypt, _ := cmd.Flags().GetBool("decrypt")
if decrypt {
Expand Down
22 changes: 16 additions & 6 deletions pkg/blueprint/templates/default.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,20 @@ local cpNodes = if std.objectHas(context, "cluster") && std.objectHas(context.cl
// Select the first node or default to null if no nodes are present
local firstNode = if std.length(cpNodes) > 0 then cpNodes[0] else null;

// Extract baseUrl from endpoint
local extractBaseUrl(endpoint) =
if endpoint == "" then "" else
local parts = std.split(endpoint, "://");
if std.length(parts) > 1 then
local hostParts = std.split(parts[1], ":");
hostParts[0]
else
local hostParts = std.split(endpoint, ":");
hostParts[0];

// Determine the endpoint, using cluster.endpoint if available, otherwise falling back to firstNode
local endpoint = if std.objectHas(context.cluster, "endpoint") then context.cluster.endpoint else if firstNode != null then firstNode.node else "";
local endpoint = if std.objectHas(context.cluster, "endpoint") then context.cluster.endpoint else if firstNode != null then firstNode.endpoint else "";
local baseUrl = extractBaseUrl(endpoint);

// Build the mirrors dynamically, only if registries are defined
local registryMirrors = if std.objectHas(context, "docker") && std.objectHas(context.docker, "registries") then
Expand Down Expand Up @@ -81,15 +93,14 @@ local terraformConfig = if platform == "local" || platform == "metal" then [
source: "core",
values: {
// Use the determined endpoint
cluster_endpoint: if endpoint != "" then "https://" + endpoint + ":6443" else "",
cluster_endpoint: if endpoint != "" then "https://" + baseUrl + ":6443" else "",
cluster_name: "talos",

// Create a list of control plane nodes
controlplanes: if std.objectHas(context.cluster, "controlplanes") && std.objectHas(context.cluster.controlplanes, "nodes") then
std.map(
function(v) {
endpoint: v.endpoint,
hostname: v.hostname,
node: v.node,
},
std.objectValues(context.cluster.controlplanes.nodes)
Expand All @@ -101,7 +112,6 @@ local terraformConfig = if platform == "local" || platform == "metal" then [
std.map(
function(v) {
endpoint: v.endpoint,
hostname: v.hostname,
node: v.node,
},
std.objectValues(context.cluster.workers.nodes)
Expand All @@ -117,7 +127,7 @@ local terraformConfig = if platform == "local" || platform == "metal" then [
apiServer: {
certSANs: [
"localhost",
endpoint,
baseUrl,
],
},
extraManifests: [
Expand All @@ -132,7 +142,7 @@ local terraformConfig = if platform == "local" || platform == "metal" then [
machine: {
certSANs: [
"localhost",
endpoint,
baseUrl,
],
network: if vmDriver == "docker-desktop" then {
interfaces: [
Expand Down
3 changes: 2 additions & 1 deletion pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
DEFAULT_TALOS_WORKER_RAM = 4
DEFAULT_TALOS_CONTROL_PLANE_CPU = 2
DEFAULT_TALOS_CONTROL_PLANE_RAM = 2
DEFAULT_TALOS_API_PORT = 50000
)

const (
Expand Down Expand Up @@ -55,7 +56,7 @@ const (
const (
// renovate: datasource=docker depName=registry
REGISTRY_DEFAULT_IMAGE = "registry:2.8.3"
REGISTRY_DEFAULT_HOST_PORT = 5002
REGISTRY_DEFAULT_HOST_PORT = 5001
)

// Default network settings
Expand Down
115 changes: 77 additions & 38 deletions pkg/services/dns_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package services
import (
"fmt"
"path/filepath"
"strings"

"github.com/compose-spec/compose-go/types"
"github.com/windsorcli/cli/pkg/constants"
Expand Down Expand Up @@ -53,12 +54,12 @@ func (s *DNSService) SetAddress(address string) error {
// GetComposeConfig sets up CoreDNS with context and domain, configures ports if localhost.
func (s *DNSService) GetComposeConfig() (*types.Config, error) {
contextName := s.configHandler.GetContext()
tld := s.configHandler.GetString("dns.domain", "test")
fullName := s.name + "." + tld
serviceName := s.GetName()
containerName := s.GetContainerName()

corednsConfig := types.ServiceConfig{
Name: fullName,
ContainerName: fullName,
Name: serviceName,
ContainerName: containerName,
Image: constants.DEFAULT_DNS_IMAGE,
Restart: "always",
Command: []string{"-conf", "/etc/coredns/Corefile"},
Expand All @@ -72,7 +73,7 @@ func (s *DNSService) GetComposeConfig() (*types.Config, error) {
},
}

if s.IsLocalhostMode() {
if s.isLocalhostMode() {
corednsConfig.Ports = []types.ServicePortConfig{
{
Target: 53,
Expand All @@ -92,80 +93,118 @@ func (s *DNSService) GetComposeConfig() (*types.Config, error) {
return &types.Config{Services: services}, nil
}

// WriteConfig generates a Corefile for DNS configuration by gathering project root, TLD, and service IPs,
// constructing DNS host entries, and appending static DNS records. It adapts the Corefile for localhost
// by adding a template for local DNS resolution. Additionally, it configures DNS forwarding by including
// specified forward addresses, ensuring DNS queries are directed appropriately. The final Corefile is
// written to the .windsor config directory
// WriteConfig generates a Corefile by collecting the project root directory, top-level domain (TLD), and IP addresses.
// It adds DNS entries for each service, ensuring that each service's hostname resolves to its IP address.
// For localhost environments, it uses a specific DNS template to handle local DNS resolution and sets up forwarding
// rules to direct DNS queries to the appropriate addresses.
// The Corefile is saved in the .windsor directory, which is used by CoreDNS to manage DNS queries for the project.
func (s *DNSService) WriteConfig() error {
projectRoot, err := s.shell.GetProjectRoot()
if err != nil {
return fmt.Errorf("error retrieving project root: %w", err)
}

tld := s.configHandler.GetString("dns.domain", "test")
networkCIDR := s.configHandler.GetString("network.cidr_block")

var (
hostEntries string
localhostHostEntries string
wildcardEntries string
localhostWildcardEntries string
)

wildcardTemplate := `
template IN A {
match ^(.*)\.%s\.$
answer "{{ .Name }} 60 IN A %s"
fallthrough
}
`
localhostTemplate := `
template IN A {
match ^(.*)\.%s\.$
answer "{{ .Name }} 60 IN A 127.0.0.1"
fallthrough
}
`

var hostEntries string
for _, service := range s.services {
composeConfig, err := service.GetComposeConfig()
if err != nil || composeConfig == nil {
continue
}
for _, svc := range composeConfig.Services {
if svc.Name != "" {
address := service.GetAddress()
if address != "" {
hostname := service.GetHostname()
if s.IsLocalhostMode() {
address = "127.0.0.1"
}
hostEntries += fmt.Sprintf(" %s %s\n", address, hostname)
if svc.Name == "" {
continue
}
address := service.GetAddress()
if address == "" {
continue
}

hostname := service.GetHostname()
escapedHostname := strings.ReplaceAll(hostname, ".", "\\.")

hostEntries += fmt.Sprintf(" %s %s\n", address, hostname)
if s.isLocalhostMode() {
localhostHostEntries += fmt.Sprintf(" 127.0.0.1 %s\n", hostname)
}
if service.SupportsWildcard() {
wildcardEntries += fmt.Sprintf(wildcardTemplate, escapedHostname, address)
if s.isLocalhostMode() {
localhostWildcardEntries += fmt.Sprintf(localhostTemplate, escapedHostname)
}
}
}
}

dnsRecords := s.configHandler.GetStringSlice("dns.records", nil)
for _, record := range dnsRecords {
for _, record := range s.configHandler.GetStringSlice("dns.records", nil) {
hostEntries += fmt.Sprintf(" %s\n", record)
if s.isLocalhostMode() {
localhostHostEntries += fmt.Sprintf(" %s\n", record)
}
}

forwardAddresses := s.configHandler.GetStringSlice("dns.forward", nil)
if len(forwardAddresses) == 0 {
forwardAddresses = []string{"1.1.1.1", "8.8.8.8"}
}
forwardAddressesStr := fmt.Sprintf("%s", forwardAddresses[0])
for _, addr := range forwardAddresses[1:] {
forwardAddressesStr += fmt.Sprintf(" %s", addr)
}
forwardAddressesStr := strings.Join(forwardAddresses, " ")

var corefileContent string
corefileContent = fmt.Sprintf(`
%s:53 {
errors
reload
loop
hosts {
serverBlockTemplate := `%s:53 {
%s hosts {
%s fallthrough
}
%s
reload
loop
forward . %s
}
.:53 {
errors
`

var corefileContent string
if s.isLocalhostMode() {
internalView := fmt.Sprintf(" view internal {\n expr incidr(client_ip(), '%s')\n }\n", networkCIDR)
corefileContent = fmt.Sprintf(serverBlockTemplate, tld, internalView, hostEntries, wildcardEntries, forwardAddressesStr)
corefileContent += fmt.Sprintf(serverBlockTemplate, tld, "", localhostHostEntries, localhostWildcardEntries, forwardAddressesStr)
} else {
corefileContent = fmt.Sprintf(serverBlockTemplate, tld, "", hostEntries, wildcardEntries, forwardAddressesStr)
}

corefileContent += `.:53 {
reload
loop
forward . 1.1.1.1 8.8.8.8
}
`, tld, hostEntries, forwardAddressesStr)
`

corefilePath := filepath.Join(projectRoot, ".windsor", "Corefile")

if err := mkdirAll(filepath.Dir(corefilePath), 0755); err != nil {
return fmt.Errorf("error creating parent folders: %w", err)
}

err = writeFile(corefilePath, []byte(corefileContent), 0644)
if err != nil {
if err := writeFile(corefilePath, []byte(corefileContent), 0644); err != nil {
return fmt.Errorf("error writing Corefile: %w", err)
}

Expand Down
Loading
Loading