Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/golangci/golangci-lint v1.51.2
github.com/google/go-querystring v1.1.0
github.com/ory/go-acc v0.2.8
gopkg.in/yaml.v2 v2.4.0
)

require (
Expand Down Expand Up @@ -178,7 +179,6 @@ require (
golang.org/x/tools v0.6.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
honnef.co/go/tools v0.4.2 // indirect
mvdan.cc/gofumpt v0.4.0 // indirect
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/cloud/image/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
)

type (
// Client is a Service to work with API Jobs.
// Client is a Service to work with API.
Client struct {
client *api.Client
}
Expand Down
62 changes: 62 additions & 0 deletions pkg/api/cloud/stack/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import (
"net/url"
"strconv"

"github.com/sitehostnz/gosh/pkg/models"
"github.com/sitehostnz/gosh/pkg/utils"
"github.com/sitehostnz/gosh/pkg/utils/dockercompose"
)

// Add creates a new cloud stack.
Expand Down Expand Up @@ -50,3 +52,63 @@ func (s *Client) Add(ctx context.Context, request AddRequest) (response AddRespo

return response, nil
}

// AddWithImage creates a new cloud stack with an image (Web Image and Service Image are supported).
func (s *Client) AddWithImage(ctx context.Context, request AddRequestWithImage) (response AddResponse, err error) {
uri := "cloud/stack/add.json"
keys := []string{
"client_id",
"server",
"name",
"label",
"enable_ssl",
"docker_compose",
}

values := url.Values{}
values.Add("client_id", s.client.ClientID)
values.Add("server", request.ServerName)
values.Add("name", request.Name)
values.Add("label", request.Label)
values.Add("enable_ssl", strconv.Itoa(request.EnableSSL))

// Set the registry path
registryPath := "registry-staging.sitehost.co.nz"
if request.ImageProvider == ImageProviderCustom {
registryPath = "registry-clients.sitehost.co.nz"
}

// Generate Docker Compose file
dockerCompose, err := dockercompose.GenerateDockerCompose(ctx, s.client, models.GenerateDockerComposeRequest{
Name: request.Name,
Label: request.Label,
RegistryPath: registryPath,
ImageCode: request.ImageCode,
})
if err != nil {
return response, err
}

values.Add("docker_compose", dockerCompose)

var vars string
for _, envVar := range request.EnvironmentVariables {
vars += fmt.Sprintf(" %s: %s\n", envVar.Name, envVar.Content)
}

if vars != "" {
values.Add("environments["+request.Name+".env]", fmt.Sprintf("vars: \n%s", vars))
keys = append(keys, "environments["+request.Name+".env]")
}

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
}
2 changes: 1 addition & 1 deletion pkg/api/cloud/stack/environment/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
)

type (
// Client is a Service to work with API Jobs.
// Client is a Service to work with API.
Client struct {
client *api.Client
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/cloud/stack/image/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package image represents a cloud stack images operations under the `/cloud/stack/image` API endpoint.
package image
24 changes: 24 additions & 0 deletions pkg/api/cloud/stack/image/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package image

import (
"context"
"errors"

"github.com/sitehostnz/gosh/pkg/models"
)

// GetImageByCode returns a image by code.
func (s *Client) GetImageByCode(ctx context.Context, request GetRequest) (response models.Image, err error) {
images, err := s.ListImages(ctx)
if err != nil {
return response, err
}

for _, image := range images.Return {
if image.Code == request.Code {
return image, nil
}
}

return response, errors.New("image not found")
}
21 changes: 21 additions & 0 deletions pkg/api/cloud/stack/image/list_all.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package image

import (
"context"
)

// ListImages returns a list of images.
func (s *Client) ListImages(ctx context.Context) (response GetResponse, err error) {
uri := "cloud/stack/image/list_all.json"

req, err := s.client.NewRequest("GET", uri, "")
if err != nil {
return response, err
}

if err := s.client.Do(ctx, req, &response); err != nil {
return response, err
}

return response, nil
}
19 changes: 19 additions & 0 deletions pkg/api/cloud/stack/image/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package image

import (
"github.com/sitehostnz/gosh/pkg/api"
)

type (
// Client is a Service to work with API.
Client struct {
client *api.Client
}
)

// New is an initialisation function.
func New(c *api.Client) *Client {
return &Client{
client: c,
}
}
8 changes: 8 additions & 0 deletions pkg/api/cloud/stack/image/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package image

type (
// GetRequest is the request to get a image by code.
GetRequest struct {
Code string `json:"code"`
}
)
11 changes: 11 additions & 0 deletions pkg/api/cloud/stack/image/response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package image

import "github.com/sitehostnz/gosh/pkg/models"

type (
// GetResponse is the response that returns a images list.
GetResponse struct {
Return []models.Image `json:"return"`
models.APIResponse
}
)
21 changes: 21 additions & 0 deletions pkg/api/cloud/stack/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ package stack

import "github.com/sitehostnz/gosh/pkg/models"

const (
// ImageProviderSiteHost is the default image provider.
ImageProviderSiteHost ImageProviderName = "sitehost"
// ImageProviderCustom is a custom image provider (client image).
ImageProviderCustom ImageProviderName = "custom"
)

type (
// ListRequest represents a listing request for stacks on a server.
ListRequest struct {
Expand All @@ -24,6 +31,20 @@ type (
EnvironmentVariables []models.EnvironmentVariable
}

// ImageProviderName is a type for image providers.
ImageProviderName string

// AddRequestWithImage represents the construction / setup of a new cloud stack.
AddRequestWithImage struct {
ServerName string `json:"server_name"`
Name string `json:"name"`
Label string `json:"label"`
EnableSSL int `json:"enable_ssl"`
ImageProvider ImageProviderName
ImageCode string `json:"image_code"`
EnvironmentVariables []models.EnvironmentVariable
}

// StopStartRestartRequest is a request to start, restart or stop a cloud stack/container.
StopStartRestartRequest struct {
ServerName string `json:"server_name"`
Expand Down
57 changes: 57 additions & 0 deletions pkg/models/docker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package models

type (
// DockerCompose represents a docker-compose.yml file.
// See https://docs.docker.com/compose/compose-file/

// Service represents a service in the docker-compose.yml file.
Service struct {
ContainerName string `yaml:"container_name"`
Environment []string `yaml:"environment"`
Expose []string `yaml:"expose"`
Image string `yaml:"image"`
Labels []string `yaml:"labels"`
Restart string `yaml:"restart"`
Volumes []string `yaml:"volumes"`
}

// Networks represents the networks in the docker-compose.yml file.
Networks struct {
Default DefaultNetwork `yaml:"default"`
}

// DefaultNetwork represents the default network in the docker-compose.yml file.
DefaultNetwork struct {
External ExternalNetwork `yaml:"external"`
}

// ExternalNetwork represents the external network in the docker-compose.yml file.
ExternalNetwork struct {
Name string `yaml:"name"`
}

// DockerCompose represents a docker-compose.yml file.
DockerCompose struct {
Version string `yaml:"version"`
Services map[string]Service `yaml:"services"`
Networks Networks `yaml:"networks"`
}

// GenerateDockerComposeRequest represents the construction / setup of a docker compose.
GenerateDockerComposeRequest struct {
Name string `json:"name"`
Label string `json:"label"`
RegistryPath string `json:"registry_path"`
ImageCode string `json:"image_code"`
}

// BuildDockerCompose represents the construction / setup of a docker compose.
BuildDockerCompose struct {
Name string `json:"name"`
Label string `json:"label"`
Image string `json:"image"`
Type string `json:"type"`
Ports []string `yaml:"ports"`
Volumes []string `yaml:"volumes"`
}
)
96 changes: 74 additions & 22 deletions pkg/models/image.go
Original file line number Diff line number Diff line change
@@ -1,30 +1,82 @@
package models

import "github.com/sitehostnz/gosh/pkg/utils"
import (
"bytes"
"encoding/json"
)

type (
// Image represents an image in the cloud images api.
Image struct {
ID string `json:"id"`
ClientID string `json:"client_id"`
Label string `json:"label"`
Code string `json:"code"`
Version string `json:"version"`
Labels string `json:"labels"`
Changelog string `json:"changelog"`
DateAdded string `json:"date_added"`
DateUpdated string `json:"date_updated"`
IsPublic utils.MaybeBool `json:"is_public"`
IsMissing utils.MaybeBool `json:"is_missing"`
ProjectID string `json:"project_id"`
RegistryID string `json:"registry_id"`
ForkedFrom string `json:"forked_from"`
Pending string `json:"pending"`
ClientName string `json:"client_name"`
ImageType string `json:"image_type"`
RegistryURL string `json:"registry_url"`
VersionCount int `json:"version_count"`
ContainerCount int `json:"container_count"`
BuildStatus string `json:"build_status"`
ID string `json:"id"`
ClientID string `json:"client_id"`
Label string `json:"label"`
Code string `json:"code"`
Labels struct {
NzSitehostImageVolumes struct {
Source any `json:"source"`
Hash string `json:"hash"`
Volumes map[string]Volume `json:"volumes"`
} `json:"nz.sitehost.image.volumes"`
NzSitehostImageProvider string `json:"nz.sitehost.image.provider"`
NzSitehostImageType string `json:"nz.sitehost.image.type"`
NzSitehostImageLabel string `json:"nz.sitehost.image.label"`
NzSitehostImagePorts PortList `json:"nz.sitehost.image.ports"`
} `json:"labels"`
Changelog string `json:"changelog"`
DateAdded string `json:"date_added"`
DateUpdated string `json:"date_updated"`
IsPublic string `json:"is_public"`
IsMissing string `json:"is_missing"`
ProjectID string `json:"project_id"`
RegistryID string `json:"registry_id"`
ForkedFrom any `json:"forked_from"`
Pending any `json:"pending"`
Versions []struct {
ID string `json:"id"`
ClientID string `json:"client_id"`
ImageID string `json:"image_id"`
Version string `json:"version"`
Labels string `json:"labels"`
DateAdded string `json:"date_added"`
DateUpdated string `json:"date_updated"`
IsMissing string `json:"is_missing"`
ForceConfig string `json:"force_config"`
BuildID string `json:"build_id"`
BuildStatus string `json:"build_status"`
Pending string `json:"pending"`
} `json:"versions"`
RegistryPath string `json:"registry_path,omitempty"`
}

// PortList represents a port list in the cloud images api.
PortList map[string]Port

// Port represents a port in the cloud images api.
Port struct {
Protocol string `json:"protocol"`
Publish bool `json:"publish"`
Exposed bool `json:"exposed"`
}

// Volume represents a volume in the cloud images api.
Volume struct {
Dest string `json:"dest"`
Mode string `json:"mode"`
}
)

// UnmarshalJSON implements the json.Unmarshaler interface to fix the port list format.
func (p *PortList) UnmarshalJSON(data []byte) error {
if bytes.Equal(data, []byte("[]")) {
*p = make(map[string]Port)
return nil
}
var m map[string]Port
err := json.Unmarshal(data, &m)
if err != nil {
return err
}
*p = m
return nil
}
Loading