pulumi-library/pkg/application/generic.go

222 lines
5.8 KiB
Go
Raw Normal View History

package application
import (
v1 "antoine-roux.tk/projects/go/pulumi-library/crds/kubernetes/certmanager/v1"
2023-11-18 20:51:42 +00:00
"antoine-roux.tk/projects/go/pulumi-library/pkg/exposition"
"antoine-roux.tk/projects/go/pulumi-library/pkg/meta"
"antoine-roux.tk/projects/go/pulumi-library/pkg/workload"
"errors"
"fmt"
appsv1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apps/v1"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"slices"
)
type Configuration struct {
Name string
Namespace string
Images []ImagesConfiguration
Dns *string
Replicas *int
Env map[string]string
AllowAllOrigin bool
}
2023-11-18 20:51:42 +00:00
type ImagesConfiguration struct {
Image string
Path string
Health string
2024-10-06 22:40:51 +00:00
Ready string
2023-11-18 20:51:42 +00:00
}
2023-11-18 20:51:42 +00:00
type CreatedApplication struct {
ApplicationName pulumi.StringOutput `pulumi:"application"`
DeploymentName []pulumi.StringOutput `pulumi:"deployment"`
}
2023-11-18 20:51:42 +00:00
type application struct {
pulumi.ResourceState
Name string
2023-11-18 20:51:42 +00:00
Namespace string
Services []service
Dns string
Replicas int
2023-11-18 20:51:42 +00:00
Env map[string]string
AllowAllOrigin bool
2023-11-18 20:51:42 +00:00
shouldCreateDns bool
shouldCreateCertificate bool
shouldCreateIngress bool
}
2023-11-18 20:51:42 +00:00
type service struct {
Image string
Path string
Health string
2024-10-06 22:40:51 +00:00
Ready string
}
2023-11-18 20:51:42 +00:00
func NewApplication(ctx *pulumi.Context, configuration *Configuration) (*CreatedApplication, error) {
2023-11-18 20:51:42 +00:00
if configuration.Name != "" && len(configuration.Images) > 0 {
2023-11-18 20:51:42 +00:00
application := &application{
Name: configuration.Name,
Namespace: configuration.Namespace,
Env: configuration.Env,
AllowAllOrigin: configuration.AllowAllOrigin,
}
var preventDuplicatePath []string
2023-11-18 20:51:42 +00:00
for _, image := range configuration.Images {
serviceConfiguration := service{
Image: image.Image,
Path: image.Path,
Health: image.Health,
2024-10-06 22:40:51 +00:00
Ready: image.Ready,
}
2023-11-18 20:51:42 +00:00
if image.Path == "" {
serviceConfiguration.Path = "/"
}
2023-11-18 20:51:42 +00:00
if image.Health == "" {
serviceConfiguration.Health = "/"
2023-10-05 22:23:14 +00:00
}
2024-10-06 22:40:51 +00:00
if image.Ready == "" {
serviceConfiguration.Ready = "/"
}
2023-11-18 20:51:42 +00:00
if slices.Contains(preventDuplicatePath, serviceConfiguration.Path) {
return nil, errors.New("duplicate path in ingress applicationConfiguration")
}
2023-11-18 20:51:42 +00:00
application.Services = append(application.Services, serviceConfiguration)
preventDuplicatePath = append(preventDuplicatePath, serviceConfiguration.Path)
}
2023-11-18 20:51:42 +00:00
if configuration.Replicas != nil {
application.Replicas = *configuration.Replicas
} else {
2023-11-18 20:51:42 +00:00
application.Replicas = 1
}
2023-11-18 20:51:42 +00:00
if configuration.Dns != nil {
application.Dns = *configuration.Dns
application.shouldCreateDns = true
application.shouldCreateCertificate = true
application.shouldCreateIngress = true
}
2023-11-18 20:51:42 +00:00
err := ctx.RegisterComponentResource("pkg:application:CreatedApplication", configuration.Name, application)
if err != nil {
return nil, err
}
2023-11-18 20:51:42 +00:00
return application.createResources(ctx)
} else {
2023-11-18 20:51:42 +00:00
return nil, errors.New("missing required value ApplicationName or Image during generic application construction")
}
}
2023-11-18 20:51:42 +00:00
func (application *application) createResources(ctx *pulumi.Context) (*CreatedApplication, error) {
createdApplication := &CreatedApplication{
ApplicationName: pulumi.String(application.Name).ToStringOutput(),
}
2023-11-18 20:51:42 +00:00
namespaceConfiguration := &meta.NamespaceConfiguration{
Name: application.Name,
Namespace: application.Namespace,
}
namespace, err := namespaceConfiguration.CreateNamespace(ctx)
if err != nil {
return nil, err
}
var deployments []*appsv1.Deployment
2023-11-18 20:51:42 +00:00
var ingressServices []exposition.IngressServices
for index, service := range application.Services {
indexedName := fmt.Sprintf("%s-%d", application.Name, index)
appLabels := pulumi.StringMap{
2023-10-04 23:31:06 +00:00
"app.kubernetes.io/name": pulumi.String(indexedName),
}
2023-11-18 20:51:42 +00:00
deploymentConfiguration := &workload.DeploymentConfiguration{
Name: indexedName,
Env: application.Env,
Replicas: application.Replicas,
ImageReference: &workload.ImageReference{
Image: service.Image,
Health: service.Health,
2024-10-06 22:40:51 +00:00
Ready: service.Ready,
2023-11-18 20:51:42 +00:00
},
}
2023-11-18 20:51:42 +00:00
deployment, err := deploymentConfiguration.CreateDeployment(ctx, namespace, application, appLabels)
if err != nil {
return nil, err
}
2023-11-18 20:51:42 +00:00
createdApplication.DeploymentName = append(createdApplication.DeploymentName, deployment.Metadata.Name().Elem())
2023-11-18 20:51:42 +00:00
serviceConfiguration := exposition.ServiceConfiguration{
2023-10-04 23:31:06 +00:00
Name: indexedName,
}
2023-11-18 20:51:42 +00:00
createdService, err := serviceConfiguration.CreateService(ctx, namespace, application, appLabels)
if err != nil {
return nil, err
}
2023-11-18 20:51:42 +00:00
ingressServices = append(ingressServices,
exposition.IngressServices{
Service: createdService,
Path: service.Path,
})
deployments = append(deployments, deployment)
}
2023-11-18 20:51:42 +00:00
if application.shouldCreateDns {
dnsConfiguration := &exposition.DnsConfiguration{
Name: application.Name,
Dns: application.Dns,
}
_, err = dnsConfiguration.CreateDNSRecord(ctx, namespace, application)
if err != nil {
return nil, err
}
}
2023-11-18 20:51:42 +00:00
var certificate *v1.Certificate
if application.shouldCreateCertificate {
certificateConfiguration := &meta.CertificateConfiguration{
Name: application.Name,
Dns: application.Dns,
}
certificate, err = certificateConfiguration.CreateCertificate(ctx, namespace, application)
if err != nil {
return nil, err
}
}
2023-11-18 20:51:42 +00:00
if application.shouldCreateIngress {
ingressConfiguration := exposition.NewIngressConfiguration(
application.Name,
application.Dns,
application.AllowAllOrigin,
ingressServices,
)
2023-11-18 20:51:42 +00:00
err = ingressConfiguration.CreateIngress(ctx, namespace, application, certificate)
if err != nil {
return nil, err
}
}
outs := pulumi.Map{}
for i, deployment := range deployments {
outs[fmt.Sprintf("deployment-%d", i)] = deployment.Metadata.Name()
}
err = ctx.RegisterResourceOutputs(application, outs)
if err != nil {
return nil, err
}
2023-11-18 20:51:42 +00:00
return createdApplication, nil
}