init repository

This commit is contained in:
2023-08-05 22:10:48 +02:00
commit d9ce80beb1
25 changed files with 2016 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
package services
import (
"fmt"
"localenv/utils"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
const (
MailhogImageName string = "mailhog/mailhog:latest"
MailhogServiceName string = "mailhog"
)
type Mailhog struct {
Service
}
func NewMailhog() Mailhog {
var nx Mailhog
nx.name = fmt.Sprintf("localenv-%s", MailhogServiceName)
nx.spec = nx.getServiceSpec(
WithIONetwork(),
WithRestartPolicy(),
)
return nx
}
func (n *Mailhog) getServiceSpec(opts ...ServiceOption) swarm.ServiceSpec {
spec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: n.name,
},
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Image: MailhogImageName,
Hostname: MailhogServiceName,
},
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &SwarmServiceReplicas,
},
},
}
for _, opt := range opts {
opt(&spec)
}
return spec
}
func (n *Mailhog) Deploy(ctx context.Context, cli *client.Client) error {
if err := utils.CreateService(ctx, cli, &n.spec); err != nil {
return err
}
if err := utils.CheckServiceHealthWithRetry(ctx, cli, n.name); err != nil {
return err
}
return nil
}
+71
View File
@@ -0,0 +1,71 @@
package services
import (
"fmt"
"localenv/utils"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
const (
NginxImageName string = "localenv-nginx:latest"
NginxServiceName string = "nginx"
NginxServicePort uint32 = 4443
)
type Nginx struct {
Service
}
func NewNginx() Nginx {
var nx Nginx
nx.name = fmt.Sprintf("localenv-%s", NginxServiceName)
nx.spec = nx.getServiceSpec(
WithIONetwork(),
WithHostEndpoint(NginxServicePort),
WithRestartPolicy(),
)
return nx
}
func (n *Nginx) getServiceSpec(opts ...ServiceOption) swarm.ServiceSpec {
spec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: n.name,
},
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Image: NginxImageName,
},
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &SwarmServiceReplicas,
},
},
}
for _, opt := range opts {
opt(&spec)
}
return spec
}
func (n *Nginx) Deploy(ctx context.Context, cli *client.Client) error {
if err := utils.CreateService(ctx, cli, &n.spec); err != nil {
return err
}
if err := utils.CheckServiceHealthWithRetry(ctx, cli, n.name); err != nil {
return err
}
return nil
}
+90
View File
@@ -0,0 +1,90 @@
package services
import (
"fmt"
"localenv/utils"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
const (
PostgresImageName string = "postgres:13.4-alpine"
PostgresServicePort uint32 = 5432
)
type Postgres struct {
Service
}
func NewPostgres(serviceName string) Postgres {
var pg Postgres
pg.name = fmt.Sprintf("localenv-postgres-%s", serviceName)
pg.spec = pg.getServiceSpec(
serviceName,
WithNetwork(serviceName),
WithRestartPolicy(),
)
return pg
}
func (p *Postgres) getServiceSpec(name string, opts ...ServiceOption) swarm.ServiceSpec {
spec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: p.name,
},
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Image: PostgresImageName,
Hostname: fmt.Sprintf("pg-%s", name),
Env: []string{
"POSTGRES_HOSTNAME=localhost",
fmt.Sprintf("POSTGRES_PORT=%d", PostgresServicePort),
fmt.Sprintf("POSTGRES_DB=%s", name),
"POSTGRES_USER=test",
"POSTGRES_PASSWORD=test",
},
Mounts: []mount.Mount{
{
Type: mount.TypeVolume,
Source: p.name,
Target: "/var/lib/postgresql/data/",
},
},
},
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &SwarmServiceReplicas,
},
},
}
for _, opt := range opts {
opt(&spec)
}
return spec
}
func (p *Postgres) Deploy(ctx context.Context, cli *client.Client) error {
if err := utils.CreateVolume(ctx, cli, p.name); err != nil {
return err
}
if err := utils.CreateService(ctx, cli, &p.spec); err != nil {
return err
}
if err := utils.CheckServiceHealthWithRetry(ctx, cli, p.name); err != nil {
return err
}
return nil
}
+85
View File
@@ -0,0 +1,85 @@
package services
import (
"fmt"
"localenv/utils"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
const (
RabbitMQImageName string = "rabbitmq:3-management-alpine"
RabbitMQServiceName string = "rabbitmq"
RabbitMQServicePort uint32 = 5672
RabbitMQServiceManagementPort uint32 = 15672
)
type RabbitMQ struct {
Service
}
func NewRabbitMQ() RabbitMQ {
var rq RabbitMQ
rq.name = fmt.Sprintf("localenv-%s", RabbitMQServiceName)
rq.spec = rq.getServiceSpec(
WithIONetwork(),
WithHostEndpoint(RabbitMQServiceManagementPort),
WithRestartPolicy(),
)
return rq
}
func (r *RabbitMQ) getServiceSpec(opts ...ServiceOption) swarm.ServiceSpec {
spec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: r.name,
},
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Image: RabbitMQImageName,
Hostname: RabbitMQServiceName,
Env: []string{
"RABBITMQ_DEFAULT_USER=intercloud",
"RABBITMQ_DEFAULT_PASS=intercloud",
},
Mounts: []mount.Mount{
{
Type: mount.TypeVolume,
Source: "mqdata",
Target: "/var/lib/rabbitmq",
},
},
},
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &SwarmServiceReplicas,
},
},
}
for _, opt := range opts {
opt(&spec)
}
return spec
}
func (r *RabbitMQ) Deploy(ctx context.Context, cli *client.Client) error {
if err := utils.CreateService(ctx, cli, &r.spec); err != nil {
return err
}
if err := utils.CheckServiceHealthWithRetry(ctx, cli, r.name); err != nil {
return err
}
return nil
}
+157
View File
@@ -0,0 +1,157 @@
package services
import (
"context"
"errors"
"fmt"
"time"
"localenv/utils"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
)
const NetworkName = "localenv"
var (
RetryServiceAttempts uint64 = 0
SwarmServiceReplicas uint64 = 1
RetryServiceDelay = 20 * time.Second
ErrNoRunningContainer = errors.New("no running container")
)
type ServiceOption func(spec *swarm.ServiceSpec)
func WithIONetwork() ServiceOption {
return WithNetwork(NetworkName)
}
func WithNetwork(name string) ServiceOption {
return func(spec *swarm.ServiceSpec) {
spec.Networks = append(spec.Networks,
swarm.NetworkAttachmentConfig{
Target: name,
Aliases: []string{name},
},
)
}
}
func WithHostEndpoint(port uint32) ServiceOption {
return func(spec *swarm.ServiceSpec) {
spec.EndpointSpec = &swarm.EndpointSpec{
Mode: "vip",
Ports: []swarm.PortConfig{
{
Protocol: "tcp",
TargetPort: port,
PublishedPort: port,
PublishMode: "host",
},
},
}
}
}
func WithRestartPolicy() ServiceOption {
return func(spec *swarm.ServiceSpec) {
spec.TaskTemplate.RestartPolicy = &swarm.RestartPolicy{
Condition: swarm.RestartPolicyConditionOnFailure,
MaxAttempts: &RetryServiceAttempts,
Delay: &RetryServiceDelay,
}
}
}
func WithPostgres(name string) ServiceOption {
return func(spec *swarm.ServiceSpec) {
if spec.TaskTemplate.ContainerSpec == nil {
return
}
spec.TaskTemplate.ContainerSpec.Env = append(
spec.TaskTemplate.ContainerSpec.Env,
"DB_TYPE=postgres",
fmt.Sprintf("POSTGRES_HOSTNAME=pg-%s", name),
fmt.Sprintf("POSTGRES_PORT=%d", PostgresServicePort),
fmt.Sprintf("POSTGRES_DB=%s", name),
"POSTGRES_USER=test",
"POSTGRES_PASSWORD=test",
)
}
}
func WithRabbitMQ() ServiceOption {
return func(spec *swarm.ServiceSpec) {
if spec.TaskTemplate.ContainerSpec == nil {
return
}
spec.TaskTemplate.ContainerSpec.Env = append(
spec.TaskTemplate.ContainerSpec.Env,
fmt.Sprintf("RABBITMQ_ENDPOINT=amqp://%s:%d", RabbitMQServiceName, RabbitMQServicePort),
"RABBITMQ_USERNAME=intercloud",
"RABBITMQ_PASSWORD=intercloud",
)
}
}
type Servicer interface {
Deploy(ctx context.Context, cli *client.Client) error
}
type Service struct {
spec swarm.ServiceSpec
name string
}
func (p *Service) GetBaseServiceSpec(serviceName, hostname, imageName, port string, command []string) swarm.ServiceSpec {
spec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: serviceName,
},
TaskTemplate: swarm.TaskSpec{
ContainerSpec: &swarm.ContainerSpec{
Hostname: hostname,
Image: imageName,
Env: []string{
fmt.Sprintf("PORT=%s", port),
},
Command: command,
},
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &SwarmServiceReplicas,
},
},
}
return spec
}
func Deploy(ctx context.Context, cli *client.Client, spec *swarm.ServiceSpec, dependencies []Servicer) error {
err := utils.CheckServiceHealth(ctx, cli, spec.Annotations.Name)
if err == nil {
return nil
}
if !errors.Is(err, utils.ErrServiceNotFound) {
return err
}
for _, deps := range dependencies {
if err := deps.Deploy(ctx, cli); err != nil {
return err
}
}
if err := utils.CreateService(ctx, cli, spec); err != nil {
return err
}
return nil
}