Skip to content
Merged
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
1 change: 1 addition & 0 deletions .lycheeignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ https://fonts.gstatic.com/
.*foo.*
.*bar.*
.*xxx.*
.*example.*
https://id.atlassian.net
https://JIRA_ID.atlassian.net
https://jira_id.atlassian.net
Expand Down
2 changes: 1 addition & 1 deletion docs/plugins/gitlab-ce-docker.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# gitlab-ce-docker plugin

This plugin installs [Gitlab-CE](https://about.gitlab.com/) in an existing docker.
This plugin installs [Gitlab-CE](https://about.gitlab.com/) in an existing docker, and the container name is `gitlab`.
## Usage

Note:
Expand Down
2 changes: 1 addition & 1 deletion docs/plugins/gitlab-ce-docker.zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# gitlab-ce-docker 插件

这个插件用来在本机已存在的 Docker 上安装 [Gitlab-CE](https://about.gitlab.com/)
这个插件用来在本机已存在的 Docker 上安装 [Gitlab-CE](https://about.gitlab.com/), 容器名为 `gitlab`。
## 使用

注意:
Expand Down
17 changes: 12 additions & 5 deletions internal/pkg/plugin/gitlabcedocker/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/mitchellh/mapstructure"

"github.com/devstream-io/devstream/pkg/util/docker"
"github.com/devstream-io/devstream/pkg/util/log"
)

Expand All @@ -16,37 +17,43 @@ func Create(options map[string]interface{}) (map[string]interface{}, error) {
return nil, err
}

defaults(&opts)

if errs := validate(&opts); len(errs) != 0 {
for _, e := range errs {
log.Errorf("Options error: %s.", e)
}
return nil, fmt.Errorf("opts are illegal")
}

op := getDockerOperator(opts)
op := GetDockerOperator(opts)

// 1. try to pull the image
// always pull the image because docker will check the image existence
if err := op.PullImage(getImageNameWithTag(opts)); err != nil {
if err := op.ImagePull(getImageNameWithTag(opts)); err != nil {
return nil, err
}

// 2. try to run the container
log.Info("Running container as the name <gitlab>")
if err := op.RunContainer(opts); err != nil {
if err := op.ContainerRun(buildDockerRunOptions(opts), dockerRunShmSizeParam); err != nil {
return nil, fmt.Errorf("failed to run container: %v", err)
}

// 3. check if the container is started successfully
if ok := op.IfContainerRunning(gitlabContainerName); !ok {
if ok := op.ContainerIfRunning(gitlabContainerName); !ok {
return nil, fmt.Errorf("failed to run container")
}

// 4. check if the volume is created successfully
volumes, err := op.ListContainerMounts(gitlabContainerName)
mounts, err := op.ContainerListMounts(gitlabContainerName)
if err != nil {
return nil, fmt.Errorf("failed to get container mounts: %v", err)
}
volumes := mounts.ExtractSources()
if docker.IfVolumesDiffer(volumes, getVolumesDirFromOptions(opts)) {
return nil, fmt.Errorf("failed to create volumes")
}

// 5. show the access url
showGitLabURL(opts)
Expand Down
22 changes: 12 additions & 10 deletions internal/pkg/plugin/gitlabcedocker/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,34 @@ func Delete(options map[string]interface{}) (bool, error) {
return false, err
}

defaults(&opts)

if errs := validate(&opts); len(errs) != 0 {
for _, e := range errs {
log.Errorf("Options error: %s.", e)
}
return false, fmt.Errorf("opts are illegal")
}

op := getDockerOperator(opts)
op := GetDockerOperator(opts)

// 1. stop the container if it is running
if ok := op.IfContainerRunning(gitlabContainerName); ok {
if err := op.StopContainer(gitlabContainerName); err != nil {
if ok := op.ContainerIfRunning(gitlabContainerName); ok {
if err := op.ContainerStop(gitlabContainerName); err != nil {
log.Errorf("Failed to stop container: %v", err)
}
}

// 2. remove the container if it exists
if ok := op.IfContainerExists(gitlabContainerName); ok {
if err := op.RemoveContainer(gitlabContainerName); err != nil {
if ok := op.ContainerIfExist(gitlabContainerName); ok {
if err := op.ContainerRemove(gitlabContainerName); err != nil {
log.Errorf("failed to remove container %v: %v", gitlabContainerName, err)
}
}

// 3. remove the image if it exists
if ok := op.IfImageExists(getImageNameWithTag(opts)); ok {
if err := op.RemoveImage(getImageNameWithTag(opts)); err != nil {
if ok := op.ImageIfExist(getImageNameWithTag(opts)); ok {
if err := op.ImageRemove(getImageNameWithTag(opts)); err != nil {
log.Errorf("failed to remove image %v: %v", getImageNameWithTag(opts), err)
}
}
Expand All @@ -58,15 +60,15 @@ func Delete(options map[string]interface{}) (bool, error) {
var errs []error

// 1. check if the container is stopped and deleted
if ok := op.IfContainerRunning(gitlabContainerName); ok {
if ok := op.ContainerIfRunning(gitlabContainerName); ok {
errs = append(errs, fmt.Errorf("failed to delete/stop container %s", gitlabContainerName))
}
if ok := op.IfContainerExists(gitlabContainerName); ok {
if ok := op.ContainerIfExist(gitlabContainerName); ok {
errs = append(errs, fmt.Errorf("failed to delete container %s", gitlabContainerName))
}

// 2. check if the image is removed
if ok := op.IfImageExists(getImageNameWithTag(opts)); ok {
if ok := op.ImageIfExist(getImageNameWithTag(opts)); ok {
errs = append(errs, fmt.Errorf("failed to delete image %s", getImageNameWithTag(opts)))
}

Expand Down
48 changes: 16 additions & 32 deletions internal/pkg/plugin/gitlabcedocker/gitlabcedocker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,32 @@ package gitlabcedocker

import (
"strings"

"github.com/devstream-io/devstream/pkg/util/docker"
"github.com/devstream-io/devstream/pkg/util/docker/dockersh"
)

const (
gitlabImageName = "gitlab/gitlab-ce"
defaultImageTag = "rc"
gitlabContainerName = "gitlab"
tcp = "tcp"
gitlabImageName = "gitlab/gitlab-ce"
defaultImageTag = "rc"
gitlabContainerName = "gitlab"
tcp = "tcp"
dockerRunShmSizeParam = "--shm-size 256m"
)

func getImageNameWithTag(opt Options) string {
var imageTag string
if opt.ImageTag == "" {
imageTag = defaultImageTag
} else {
imageTag = opt.ImageTag
}
return gitlabImageName + ":" + imageTag
return gitlabImageName + ":" + opt.ImageTag
}

// dockerOperator is an interface for docker operations
// It is implemented by sshDockerOperator
// in the future, we can add other implementations such as sshDockerOperator
type dockerOperator interface {
IfImageExists(imageName string) bool
PullImage(image string) error
RemoveImage(image string) error

IfContainerExists(container string) bool
IfContainerRunning(container string) bool
RunContainer(options Options) error
StopContainer(container string) error
RemoveContainer(container string) error

ListContainerMounts(container string) ([]string, error)

GetContainerHostname(container string) (string, error)
GetContainerPortBinding(container, containerPort, protocol string) (hostPort string, err error)
func defaults(opts *Options) {
if opts.ImageTag == "" {
opts.ImageTag = defaultImageTag
}
}

func getDockerOperator(_ Options) dockerOperator {
// just return a sshDockerOperator for now
return &sshDockerOperator{}
func GetDockerOperator(_ Options) docker.Operator {
// just return a ShellOperator for now
return &dockersh.ShellOperator{}
}

type gitlabResource struct {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package gitlabcedocker_test
package gitlabcedocker

import (
"testing"
Expand Down
43 changes: 36 additions & 7 deletions internal/pkg/plugin/gitlabcedocker/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package gitlabcedocker

import "path/filepath"
import (
"path/filepath"

"github.com/devstream-io/devstream/pkg/util/docker"
)

// Options is the struct for configurations of the gitlab-ce-docker plugin.
type Options struct {
Expand All @@ -14,13 +18,38 @@ type Options struct {
ImageTag string `mapstructure:"image_tag"`
}

// getVolumesDirFromOptions returns the volumes' directory from the options.
// getVolumesDirFromOptions returns host directories of the volumes from the options.
func getVolumesDirFromOptions(opts Options) []string {
volumesDirFromOptions := []string{
filepath.Join(opts.GitLabHome, "config"),
filepath.Join(opts.GitLabHome, "data"),
filepath.Join(opts.GitLabHome, "logs"),
volumes := buildDockerVolumes(opts)
return volumes.ExtractHostPaths()
}

func buildDockerVolumes(opts Options) docker.Volumes {
volumes := []docker.Volume{
{HostPath: filepath.Join(opts.GitLabHome, "config"), ContainerPath: "/etc/gitlab"},
{HostPath: filepath.Join(opts.GitLabHome, "data"), ContainerPath: "/var/opt/gitlab"},
{HostPath: filepath.Join(opts.GitLabHome, "logs"), ContainerPath: "/var/log/gitlab"},
}

return volumesDirFromOptions
return volumes
}

func buildDockerRunOptions(opts Options) docker.RunOptions {
dockerRunOpts := docker.RunOptions{}
dockerRunOpts.ImageName = gitlabImageName
dockerRunOpts.ImageTag = opts.ImageTag
dockerRunOpts.Hostname = opts.Hostname
dockerRunOpts.ContainerName = gitlabContainerName
dockerRunOpts.RestartAlways = true

portPublishes := []docker.PortPublish{
{HostPort: opts.SSHPort, ContainerPort: 22},
{HostPort: opts.HTTPPort, ContainerPort: 80},
{HostPort: opts.HTTPSPort, ContainerPort: 443},
}
dockerRunOpts.PortPublishes = portPublishes

dockerRunOpts.Volumes = buildDockerVolumes(opts)

return dockerRunOpts
}
36 changes: 32 additions & 4 deletions internal/pkg/plugin/gitlabcedocker/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package gitlabcedocker
import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/devstream-io/devstream/pkg/util/docker"
)

var _ = Describe("Options", func() {
Expand All @@ -13,16 +15,16 @@ var _ = Describe("Options", func() {
opts = Options{
GitLabHome: "/srv/gitlab",
Hostname: "gitlab.example.com",
SSHPort: 22,
HTTPPort: 80,
HTTPSPort: 443,
SSHPort: 8122,
HTTPPort: 8180,
HTTPSPort: 8443,
RmDataAfterDelete: false,
ImageTag: "rc",
}
})

Describe("getVolumesDirFromOptions func", func() {
Context("when the options is valid", func() {
When("the options is valid", func() {
It("should return the volumes' directory", func() {
volumesDirFromOptions := getVolumesDirFromOptions(opts)
Expect(volumesDirFromOptions).To(Equal([]string{
Expand All @@ -33,4 +35,30 @@ var _ = Describe("Options", func() {
})
})
})

Describe("buildDockerRunOptions func", func() {
It("should build the docker run options successfully", func() {
runOptsBuild := buildDockerRunOptions(opts)
runOptsExpect := docker.RunOptions{
ImageName: "gitlab/gitlab-ce",
ImageTag: "rc",
Hostname: "gitlab.example.com",
ContainerName: "gitlab",
RestartAlways: true,
PortPublishes: []docker.PortPublish{
{HostPort: 8122, ContainerPort: 22},
{HostPort: 8180, ContainerPort: 80},
{HostPort: 8443, ContainerPort: 443},
},
Volumes: []docker.Volume{
{HostPath: "/srv/gitlab/config", ContainerPath: "/etc/gitlab"},
{HostPath: "/srv/gitlab/data", ContainerPath: "/var/opt/gitlab"},
{HostPath: "/srv/gitlab/logs", ContainerPath: "/var/log/gitlab"},
},
}

Expect(runOptsBuild).To(Equal(runOptsExpect))
})

})
})
19 changes: 11 additions & 8 deletions internal/pkg/plugin/gitlabcedocker/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,50 @@ func Read(options map[string]interface{}) (map[string]interface{}, error) {
return nil, err
}

defaults(&opts)

if errs := validate(&opts); len(errs) != 0 {
for _, e := range errs {
log.Errorf("Options error: %s.", e)
}
return nil, fmt.Errorf("opts are illegal")
}

op := getDockerOperator(opts)
op := GetDockerOperator(opts)

// 1. get running status
running := op.IfContainerRunning(gitlabContainerName)
running := op.ContainerIfRunning(gitlabContainerName)
if !running {
return (&gitlabResource{}).toMap(), nil
}

// 2. get volumes(gitlab_home)
volumes, err := op.ListContainerMounts(gitlabContainerName)
// 2. get volumes
mounts, err := op.ContainerListMounts(gitlabContainerName)
if err != nil {
// `Read` shouldn't return errors even if failed to read ports, volumes, hostname.
// because:
// 1. when the docker is stopped it could cause these errors.
// 2. if Read failed, the following steps contain the docker's restart will be aborted.
log.Errorf("failed to get container mounts: %v", err)
}
volumes := mounts.ExtractSources()

// 3. get hostname
hostname, err := op.GetContainerHostname(gitlabContainerName)
hostname, err := op.ContainerGetHostname(gitlabContainerName)
if err != nil {
log.Errorf("failed to get container hostname: %v", err)
}

// 4. get port bindings
SSHPort, err := op.GetContainerPortBinding(gitlabContainerName, "22", tcp)
SSHPort, err := op.ContainerGetPortBinding(gitlabContainerName, "22", tcp)
if err != nil {
log.Errorf("failed to get container ssh port: %v", err)
}
HTTPPort, err := op.GetContainerPortBinding(gitlabContainerName, "80", tcp)
HTTPPort, err := op.ContainerGetPortBinding(gitlabContainerName, "80", tcp)
if err != nil {
log.Errorf("failed to get container http port: %v", err)
}
HTTPSPort, err := op.GetContainerPortBinding(gitlabContainerName, "443", tcp)
HTTPSPort, err := op.ContainerGetPortBinding(gitlabContainerName, "443", tcp)
if err != nil {
log.Errorf("failed to get container https port: %v", err)
}
Expand Down
Loading