diff --git a/pkg/api/cloud/stack/add.go b/pkg/api/cloud/stack/add.go index c1058e8..655429f 100644 --- a/pkg/api/cloud/stack/add.go +++ b/pkg/api/cloud/stack/add.go @@ -6,8 +6,10 @@ import ( "net/url" "strconv" + "github.com/sitehostnz/gosh/pkg/api/cloud/stack/image" "github.com/sitehostnz/gosh/pkg/models" "github.com/sitehostnz/gosh/pkg/utils" + "gopkg.in/yaml.v2" ) // Add creates a new cloud stack. @@ -72,7 +74,7 @@ func (s *Client) AddWithImage(ctx context.Context, request AddRequestWithImage) values.Add("enable_ssl", strconv.Itoa(request.EnableSSL)) // Generate Docker Compose file - dockerCompose, err := utils.GenerateDockerCompose(ctx, s.client, models.GenerateDockerComposeRequest{ + dockerCompose, err := s.GenerateDockerCompose(ctx, models.GenerateDockerComposeRequest{ Name: request.Name, Label: request.Label, ImageCode: request.ImageCode, @@ -104,3 +106,87 @@ func (s *Client) AddWithImage(ctx context.Context, request AddRequestWithImage) return response, nil } + +// GenerateDockerCompose generates a docker compose file for a stack. +func (s *Client) GenerateDockerCompose(ctx context.Context, request models.GenerateDockerComposeRequest) (dockerCompose string, err error) { + // Get the image + i := image.New(s.client) + image, err := i.GetImageByCode(ctx, image.GetRequest{Code: request.ImageCode}) + if err != nil { + return dockerCompose, err + } + + // registry url (staging) + registryPath := "registry-staging.sitehost.co.nz" + imageLastVersion := image.Versions[len(image.Versions)-1].Version + + // create volumes and ports + volumes := []string{} + for folder, volume := range image.Labels.NzSitehostImageVolumes.Volumes { + volumes = append(volumes, "/data/docker0/"+image.Labels.NzSitehostImageType+"/"+request.Name+"/"+folder+":"+volume.Dest+":"+volume.Mode) + } + + ports := []string{} + + for port, portInfo := range image.Labels.NzSitehostImagePorts { + if portInfo.Exposed { + ports = append(ports, port+"/"+portInfo.Protocol) + } + } + + compose, err := buildDockerCompose(models.BuildDockerCompose{ + Name: request.Name, + Label: request.Label, + Image: registryPath + "/" + image.Code + ":" + imageLastVersion, + Type: image.Labels.NzSitehostImageType, + Ports: ports, + Volumes: volumes, + }) + if err != nil { + return dockerCompose, err + } + + return compose, nil +} + +func buildDockerCompose(request models.BuildDockerCompose) (dockerCompose string, err error) { + // Create docker compose file + compose := models.DockerCompose{ + Version: "2.1", + Services: map[string]models.Service{ + request.Name: { + ContainerName: request.Name, + Environment: []string{ + "VIRTUAL_HOST=" + request.Label, + "CERT_NAME=" + request.Label, + }, + Expose: request.Ports, + Image: request.Image, + Labels: []string{ + "nz.sitehost.container.website.vhosts=" + request.Label, + "nz.sitehost.container.image_update=True", + "nz.sitehost.container.label=" + request.Label, + "nz.sitehost.container.type=" + request.Type, + "nz.sitehost.container.monitored=True", + "nz.sitehost.container.backup_disable=False", + }, + Restart: "unless-stopped", + Volumes: request.Volumes, + }, + }, + Networks: models.Networks{ + Default: models.DefaultNetwork{ + External: models.ExternalNetwork{ + Name: "infra_default", + }, + }, + }, + } + + composeYaml, err := yaml.Marshal(&compose) + if err != nil { + return dockerCompose, err + } + + return string(composeYaml), nil +} diff --git a/pkg/api/cloud/stack/delete.go b/pkg/api/cloud/stack/delete.go new file mode 100644 index 0000000..57f4c4f --- /dev/null +++ b/pkg/api/cloud/stack/delete.go @@ -0,0 +1,32 @@ +package stack + +import ( + "context" + "net/url" + + "github.com/sitehostnz/gosh/pkg/utils" +) + +// Delete removes a cloud stack. +func (s *Client) Delete(ctx context.Context, request DeleteRequest) (response ActionResponse, err error) { + uri := "cloud/stack/delete.json" + keys := []string{ + "server", + "name", + } + + values := url.Values{} + values.Add("server", request.Server) + values.Add("name", request.Name) + + req, err := s.client.NewRequest("POST", uri, utils.Encode(values, keys)) + if err != nil { + return response, err + } + + if err := s.client.Do(ctx, req, &response); err != nil { + return response, err + } + + return response, nil +} diff --git a/pkg/api/cloud/stack/request.go b/pkg/api/cloud/stack/request.go index e63134d..c7bff0d 100644 --- a/pkg/api/cloud/stack/request.go +++ b/pkg/api/cloud/stack/request.go @@ -14,6 +14,12 @@ type ( Name string `json:"name"` } + // DeleteRequest represents a request to delete a specific stack. + DeleteRequest struct { + Server string `json:"server"` + Name string `json:"name"` + } + // AddRequest represents the construction / setup of a new cloud stack. AddRequest struct { ServerName string `json:"server_name"` diff --git a/pkg/api/cloud/stack/response.go b/pkg/api/cloud/stack/response.go index f3b0625..d4b1973 100644 --- a/pkg/api/cloud/stack/response.go +++ b/pkg/api/cloud/stack/response.go @@ -28,8 +28,8 @@ type ( models.APIResponse } - // StartStopRestartResponse represents the response from start/stop/restart actions. - StartStopRestartResponse struct { + // ActionResponse represents the response from start/stop/restart/delete actions. + ActionResponse struct { Return struct { JobID string `json:"job_id"` } `json:"return"` diff --git a/pkg/api/cloud/stack/restart.go b/pkg/api/cloud/stack/restart.go index 21c9ad0..c94294d 100644 --- a/pkg/api/cloud/stack/restart.go +++ b/pkg/api/cloud/stack/restart.go @@ -5,7 +5,7 @@ import ( ) // Restart restarts a stack on the given server. -func (s *Client) Restart(ctx context.Context, request StopStartRestartRequest) (response StartStopRestartResponse, err error) { +func (s *Client) Restart(ctx context.Context, request StopStartRestartRequest) (response ActionResponse, err error) { uri := "cloud/stack/restart.json" return s.stopStartRestart(ctx, request, uri) } diff --git a/pkg/api/cloud/stack/start.go b/pkg/api/cloud/stack/start.go index ec7c4e9..a817c98 100644 --- a/pkg/api/cloud/stack/start.go +++ b/pkg/api/cloud/stack/start.go @@ -5,7 +5,7 @@ import ( ) // Start starts a cloud stack on a given server. -func (s *Client) Start(ctx context.Context, request StopStartRestartRequest) (response StartStopRestartResponse, err error) { +func (s *Client) Start(ctx context.Context, request StopStartRestartRequest) (response ActionResponse, err error) { uri := "cloud/stack/start.json" return s.stopStartRestart(ctx, request, uri) } diff --git a/pkg/api/cloud/stack/stop.go b/pkg/api/cloud/stack/stop.go index 4b7a060..52116be 100644 --- a/pkg/api/cloud/stack/stop.go +++ b/pkg/api/cloud/stack/stop.go @@ -5,7 +5,7 @@ import ( ) // Stop is for stopping a cloud stack on a given server. -func (s *Client) Stop(ctx context.Context, request StopStartRestartRequest) (response StartStopRestartResponse, err error) { +func (s *Client) Stop(ctx context.Context, request StopStartRestartRequest) (response ActionResponse, err error) { uri := "cloud/stack/stop.json" return s.stopStartRestart(ctx, request, uri) } diff --git a/pkg/api/cloud/stack/stopstartrestart.go b/pkg/api/cloud/stack/stopstartrestart.go index 5dc0fea..ea81a4e 100644 --- a/pkg/api/cloud/stack/stopstartrestart.go +++ b/pkg/api/cloud/stack/stopstartrestart.go @@ -7,7 +7,7 @@ import ( ) // stopStartRestart is the common function for stop, start and restart actions. -func (s *Client) stopStartRestart(ctx context.Context, request StopStartRestartRequest, uri string) (response StartStopRestartResponse, err error) { +func (s *Client) stopStartRestart(ctx context.Context, request StopStartRestartRequest, uri string) (response ActionResponse, err error) { keys := []string{ "apikey", "client_id", diff --git a/pkg/utils/docker.go b/pkg/utils/docker.go deleted file mode 100644 index 62f6830..0000000 --- a/pkg/utils/docker.go +++ /dev/null @@ -1,94 +0,0 @@ -package utils - -import ( - "context" - - "github.com/sitehostnz/gosh/pkg/api" - "github.com/sitehostnz/gosh/pkg/api/cloud/image" - "github.com/sitehostnz/gosh/pkg/models" - "gopkg.in/yaml.v2" -) - -// GenerateDockerCompose generates a docker compose file for a stack. -func GenerateDockerCompose(ctx context.Context, client *api.Client, request models.GenerateDockerComposeRequest) (dockerCompose string, err error) { - // Get the image - i := image.New(client) - image, err := i.GetImageByCode(ctx, image.GetRequest{Code: request.ImageCode}) - if err != nil { - return dockerCompose, err - } - - // registry url (staging) - registryPath := "registry-staging.sitehost.co.nz" - imageLastVersion := image.Versions[len(image.Versions)-1].Version - - // create volumes and ports - volumes := []string{} - for folder, volume := range image.Labels.NzSitehostImageVolumes.Volumes { - volumes = append(volumes, "/data/docker0/"+image.Labels.NzSitehostImageType+"/"+request.Name+"/"+folder+":"+volume.Dest+":"+volume.Mode) - } - - ports := []string{} - - for port, portInfo := range image.Labels.NzSitehostImagePorts { - if portInfo.Exposed { - ports = append(ports, port+"/"+portInfo.Protocol) - } - } - - compose, err := buildDockerCompose(models.BuildDockerCompose{ - Name: request.Name, - Label: request.Label, - Image: registryPath + "/" + image.Code + ":" + imageLastVersion, - Type: image.Labels.NzSitehostImageType, - Ports: ports, - Volumes: volumes, - }) - if err != nil { - return dockerCompose, err - } - - return compose, nil -} - -func buildDockerCompose(request models.BuildDockerCompose) (dockerCompose string, err error) { - // Create docker compose file - compose := models.DockerCompose{ - Version: "2.1", - Services: map[string]models.Service{ - request.Name: { - ContainerName: request.Name, - Environment: []string{ - "VIRTUAL_HOST=" + request.Label, - "CERT_NAME=" + request.Label, - }, - Expose: request.Ports, - Image: request.Image, - Labels: []string{ - "nz.sitehost.container.website.vhosts=" + request.Label, - "nz.sitehost.container.image_update=True", - "nz.sitehost.container.label=" + request.Label, - "nz.sitehost.container.type=" + request.Type, - "nz.sitehost.container.monitored=True", - "nz.sitehost.container.backup_disable=False", - }, - Restart: "unless-stopped", - Volumes: request.Volumes, - }, - }, - Networks: models.Networks{ - Default: models.DefaultNetwork{ - External: models.ExternalNetwork{ - Name: "infra_default", - }, - }, - }, - } - - composeYaml, err := yaml.Marshal(&compose) - if err != nil { - return dockerCompose, err - } - - return string(composeYaml), nil -}