init repository
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user