diff --git a/src/Aspirate.Commands/Actions/Manifests/GenerateDockerComposeManifestAction.cs b/src/Aspirate.Commands/Actions/Manifests/GenerateDockerComposeManifestAction.cs index 2dbe5ed..21b4917 100644 --- a/src/Aspirate.Commands/Actions/Manifests/GenerateDockerComposeManifestAction.cs +++ b/src/Aspirate.Commands/Actions/Manifests/GenerateDockerComposeManifestAction.cs @@ -85,7 +85,7 @@ private static List CreateVolumes(List services) private void ProcessIndividualComponent(KeyValuePair resource, List services) { - if (AspirateState.IsNotDeployable(resource.Value)) + if (CurrentState.IsNotDeployable(resource.Value)) { return; } @@ -103,6 +103,7 @@ private void ProcessIndividualComponent(KeyValuePair resource, Resource = resource, WithDashboard = CurrentState.IncludeDashboard, ComposeBuilds = CurrentState.ComposeBuilds?.Any(x=> x == resource.Key) ?? false, + CurrentState = CurrentState }); if (response.IsProject) diff --git a/src/Aspirate.Commands/Actions/Manifests/GenerateKustomizeManifestsAction.cs b/src/Aspirate.Commands/Actions/Manifests/GenerateKustomizeManifestsAction.cs index 3ed5845..5a719a8 100644 --- a/src/Aspirate.Commands/Actions/Manifests/GenerateKustomizeManifestsAction.cs +++ b/src/Aspirate.Commands/Actions/Manifests/GenerateKustomizeManifestsAction.cs @@ -64,7 +64,7 @@ private async Task ProcessIndividualResourceManifests(KeyValuePair CreateManifests(CreateManifestsOptions options) => // Do nothing for dapr, they are there for annotations on services. Task.FromResult(true); + + public override List CreateKubernetesObjects(CreateKubernetesObjectsOptions options) => []; + + public override ComposeService CreateComposeEntry(CreateComposeEntryOptions options) + { + var response = new ComposeService(); + + var daprResource = options.Resource.Value as DaprResource; + + var commands = new List + { + "./daprd", + "-app-id", + daprResource.Metadata.AppId, + }; + + var childResource = options.CurrentState.AllSelectedSupportedComponents.FirstOrDefault(x => x.Key == daprResource.Metadata.Application); + + if (childResource.Value is IResourceWithBinding childBinding) + { + var firstPort = childBinding.Bindings.FirstOrDefault(); + + commands.Add("-app-port"); + commands.Add(firstPort.Value.Port?.ToString() ?? "8080"); + } + + response.Service = new Shared.Models.Compose.ComposeServiceBuilder() + .WithName(options.Resource.Key) + .WithImage("daprio/daprd:latest") + .WithCommands(commands.ToArray()) + .WithDependencies(daprResource.Metadata.Application) + .WithNetworkMode($"service:{childResource.Key}") + .WithRestartPolicy(ERestartMode.UnlessStopped) + .Build(); + + return response; + } } diff --git a/src/Aspirate.Shared/Inputs/BaseCreateOptions.cs b/src/Aspirate.Shared/Inputs/BaseCreateOptions.cs index 74bfd68..986d850 100644 --- a/src/Aspirate.Shared/Inputs/BaseCreateOptions.cs +++ b/src/Aspirate.Shared/Inputs/BaseCreateOptions.cs @@ -25,4 +25,5 @@ public abstract class BaseCreateOptions /// public bool? WithPrivateRegistry { get; set; } + public AspirateState? CurrentState { get; set; } } diff --git a/src/Aspirate.Shared/Models/Aspirate/AspirateState.cs b/src/Aspirate.Shared/Models/Aspirate/AspirateState.cs index b402315..91eb387 100644 --- a/src/Aspirate.Shared/Models/Aspirate/AspirateState.cs +++ b/src/Aspirate.Shared/Models/Aspirate/AspirateState.cs @@ -182,8 +182,15 @@ public class AspirateState : public void AppendToFinalResources(string key, Resource resource) => FinalResources.Add(key, resource); - public static bool IsNotDeployable(Resource resource) => - (resource is DaprResource or ParameterResource or ValueResource); + public bool IsNotDeployable(Resource resource) + { + if (OutputFormat.Equals("compose", StringComparison.OrdinalIgnoreCase)) + { + return (resource is ParameterResource or ValueResource); + } + + return (resource is DaprResource or ParameterResource or ValueResource); + } [JsonIgnore] public bool? ReplaceSecrets { get; set; } diff --git a/src/Aspirate.Shared/Models/Compose/ComposeService.cs b/src/Aspirate.Shared/Models/Compose/ComposeService.cs new file mode 100644 index 0000000..8942f7e --- /dev/null +++ b/src/Aspirate.Shared/Models/Compose/ComposeService.cs @@ -0,0 +1,7 @@ +namespace Aspirate.Shared.Models.Compose; + +public class ComposeService : Service +{ + [YamlMember(Alias = "network_mode")] + public string? NetworkMode { get; set; } +} diff --git a/src/Aspirate.Shared/Models/Compose/ComposeServiceBuilder.cs b/src/Aspirate.Shared/Models/Compose/ComposeServiceBuilder.cs new file mode 100644 index 0000000..2827126 --- /dev/null +++ b/src/Aspirate.Shared/Models/Compose/ComposeServiceBuilder.cs @@ -0,0 +1,233 @@ +using DockerComposeBuilder.Builders.Base; +using DockerComposeBuilder.Builders.Services; +using DockerComposeBuilder.Enums; + +namespace Aspirate.Shared.Models.Compose; + +public class ComposeServiceBuilder : BaseBuilder +{ + protected BuildBuilder? BuildBuilder; + + public ComposeServiceBuilder() + { + } + + public ComposeServiceBuilder WithName(string name) + { + WorkingObject.Name = name; + + return this; + } + + public ComposeServiceBuilder WithContainerName(string containerName) + { + WorkingObject.ContainerName = containerName; + return this; + } + + public ComposeServiceBuilder WithDependencies(params string[] services) + { + WorkingObject.DependsOn ??= new List(); + + var dependsOnList = WorkingObject.DependsOn; + + dependsOnList?.AddRange(services); + return this; + } + + public ComposeServiceBuilder WithDependencies(params Service[] services) + { + return WithDependencies(services.Select(t => t.Name).ToArray()); + } + + public ComposeServiceBuilder WithHealthCheck(Action healthCheck) + { + WorkingObject.HealthCheck ??= new HealthCheck(); + + healthCheck(WorkingObject.HealthCheck); + + return this; + } + + public ComposeServiceBuilder WithEnvironment(IDictionary environmentMappings) + { + WorkingObject.Environment ??= new Dictionary(); + + return AddToDictionary(WorkingObject.Environment, environmentMappings); + } + + public ComposeServiceBuilder WithEnvironment(Action> environmentExpression) + { + WorkingObject.Environment ??= new Dictionary(); + + environmentExpression(WorkingObject.Environment); + + return this; + } + + public ComposeServiceBuilder WithExposed(params string[] exposed) + { + if (WorkingObject.Expose == null) + { + WorkingObject.Expose = new List(); + } + + WorkingObject.Expose.AddRange(exposed); + return this; + } + + public ComposeServiceBuilder WithExposed(params object[] exposed) + { + WorkingObject.Expose ??= new List(); + + WorkingObject.Expose.AddRange(exposed.Select(t => t.ToString())!); + return this; + } + + public ComposeServiceBuilder WithHostname(string hostname) + { + WorkingObject.Hostname = hostname; + return this; + } + + public ComposeServiceBuilder WithNetworkMode(string networkMode) + { + WorkingObject.NetworkMode = networkMode; + return this; + } + + public ComposeServiceBuilder WithLabels(IDictionary labels) + { + WorkingObject.Labels ??= new Dictionary(); + + return AddToDictionary(WorkingObject.Labels, labels); + } + + public ComposeServiceBuilder WithLabels(Action> environmentExpression) + { + WorkingObject.Labels ??= new Dictionary(); + + environmentExpression(WorkingObject.Labels); + + return this; + } + + public ComposeServiceBuilder WithBuild(Action build) + { + BuildBuilder ??= new BuildBuilder(); + + build(BuildBuilder); + + return this; + } + + public ComposeServiceBuilder WithImage(string image) + { + WorkingObject.Image = image; + return this; + } + + public ComposeServiceBuilder WithPrivileged(bool? privileged = true) + { + WorkingObject.Privileged = privileged; + return this; + } + + public ComposeServiceBuilder WithNetworks(params string[] networks) + { + if (WorkingObject.Networks == null) + { + WorkingObject.Networks = new List(); + } + + WorkingObject.Networks.AddRange(networks); + return this; + } + + public ComposeServiceBuilder WithNetworks(params Network[] networks) + { + if (WorkingObject.Networks == null) + { + WorkingObject.Networks = new List(); + } + + WorkingObject.Networks.AddRange(networks.Select(t => t.Name)); + return this; + } + + public ComposeServiceBuilder WithPortMappings(params Port[] mappings) + { + if (WorkingObject.Ports == null) + { + WorkingObject.Ports = new List(); + } + + WorkingObject.Ports.AddRange(mappings); + return this; + } + + public ComposeServiceBuilder WithExtraHosts(params string[] extraHosts) + { + if (WorkingObject.ExtraHosts == null) + { + WorkingObject.ExtraHosts = new List(); + } + + WorkingObject.ExtraHosts.AddRange(extraHosts); + return this; + } + + public ComposeServiceBuilder WithCommands(params string[] commands) + { + if (WorkingObject.Commands == null) + { + WorkingObject.Commands = new List(); + } + + WorkingObject.Commands.AddRange(commands); + return this; + } + + public ComposeServiceBuilder WithRestartPolicy(ERestartMode mode) + { + WorkingObject.Restart = mode; + return this; + } + + public ComposeServiceBuilder WithSecrets(params string[] secrets) + { + if (WorkingObject.Secrets == null) + { + WorkingObject.Secrets = new List(); + } + + WorkingObject.Secrets.AddRange(secrets); + return this; + } + + public ComposeServiceBuilder WithSecrets(params Secret[] secrets) + { + return WithSecrets(secrets.Select(t => t.Name).ToArray()); + } + + public ComposeServiceBuilder WithVolumes(params string[] volumes) + { + if (WorkingObject.Volumes == null) + { + WorkingObject.Volumes = new List(); + } + + WorkingObject.Volumes.AddRange(volumes); + return this; + } + + public override ComposeService Build() + { + if (BuildBuilder != null) + { + WorkingObject.Build = BuildBuilder.Build(); + } + + return base.Build(); + } +}