blob: 8c36f899cbf04c7c90506c505b983c66147fdba1 [file] [log] [blame]
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package common
import (
"fmt"
"strings"
"time"
"k8s.io/klog/v2"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"golang.org/x/net/context"
"github.com/apache/incubator-kie-kogito-serverless-operator/container-builder/util/log"
)
func GetDockerConnection() (*client.Client, error) {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
fmt.Println(err)
return nil, err
}
return cli, nil
}
func GetCustomDockerConnectionWithIP(ip string) (*client.Client, error) {
return client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation(), client.WithHost(ip))
}
func GetCustomRegistry() (DockerLocalRegistry, *client.Client, error) {
connectionLocal, err := GetCustomDockerConnectionWithIP(REGISTRY_CONTAINER_URL_FROM_DOCKER_SOCKET)
if err != nil {
klog.V(log.E).ErrorS(err, "error during Get Custom Registry")
return DockerLocalRegistry{}, nil, err
}
d := DockerLocalRegistry{Connection: connectionLocal}
return d, connectionLocal, nil
}
func (d DockerLocalRegistry) getConnection() (*client.Client, error) {
connectionLocal := d.Connection
if connectionLocal == nil {
return GetDockerConnection()
}
return connectionLocal, nil
}
func (d DockerLocalRegistry) StartRegistry() string {
//wait until Podman registry shutdown in the podman tests
for {
time.Sleep(1 * time.Second)
if IsPortAvailable("5000") {
break
}
}
ctx := context.Background()
registryID := d.GetRegistryRunningID()
if len(registryID) > 0 {
klog.V(log.I).InfoS("Registry ID is already running", "ID", registryID)
return registryID
}
if !d.IsRegistryImagePresent() {
klog.V(log.I).InfoS("Registry Image Pull")
_, err := d.Connection.ImagePull(ctx, REGISTRY_IMG, types.ImagePullOptions{})
if err != nil {
fmt.Println(err)
return ""
}
}
time.Sleep(2 * time.Second) // needed on CI
klog.V(log.I).InfoS("Registry Container Create")
resp, err := d.Connection.ContainerCreate(ctx, &container.Config{
Image: REGISTRY_IMG,
ExposedPorts: nat.PortSet{"5000": struct{}{}},
},
&container.HostConfig{
PortBindings: map[nat.Port][]nat.PortBinding{nat.Port("5000"): {{HostIP: "127.0.0.1", HostPort: "5000"}}},
},
nil,
nil,
REGISTRY_IMG)
if err != nil {
klog.V(log.E).ErrorS(err, "error during Registry Container Create")
}
klog.V(log.I).InfoS("Starting Registry Container")
if err := d.Connection.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
klog.V(log.E).ErrorS(err, "error during Start Registry Container")
return ""
}
// give some time to start
klog.V(log.I).InfoS("Waiting 4 seconds")
time.Sleep(4 * time.Second)
return d.GetRegistryRunningID()
}
func (d DockerLocalRegistry) StopRegistry() bool {
registryID := d.GetRegistryRunningID()
if len(registryID) > 0 {
klog.V(log.I).InfoS("StopRegistry Kill Container", "ID", registryID)
ctx := context.Background()
_ = d.Connection.ContainerKill(ctx, registryID, "SIGKILL")
klog.V(log.I).InfoS("StopRegistry Removing Container", "ID", registryID)
err := d.Connection.ContainerRemove(ctx, registryID, types.ContainerRemoveOptions{})
if err != nil {
klog.V(log.E).ErrorS(err, "error during Stop Registry")
return false
}
}
return true
}
func (d DockerLocalRegistry) StopAndRemoveContainer(containerID string) bool {
if len(containerID) > 0 {
ctx := context.Background()
klog.V(log.I).InfoS("Docker StopAndRemoveContainer Kill registry container", "ID", containerID)
_ = d.Connection.ContainerKill(ctx, containerID, "SIGKILL")
klog.V(log.I).InfoS("Docker StopAndRemoveContainer Removing container", "ID", containerID)
err := d.Connection.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{})
return err == nil
}
fmt.Println("Docker StopAndRemoveContainer Invalid ID " + containerID)
return true
}
func (d DockerLocalRegistry) GetRegistryRunningID() string {
containers, err := d.Connection.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
fmt.Println(err)
return ""
}
for _, container := range containers {
if container.Image == REGISTRY_IMG {
return container.ID
}
}
return ""
}
func (d DockerLocalRegistry) IsRegistryImagePresent() bool {
imageList, err := d.Connection.ImageList(context.Background(), types.ImageListOptions{})
if err != nil {
return false
}
for _, imagex := range imageList {
if (len(imagex.RepoTags) > 0 && imagex.RepoTags[0] == REGISTRY_IMG) || (imagex.RepoDigests != nil && strings.HasPrefix(imagex.RepoDigests[0], REGISTRY_IMG)) {
return true
}
}
return false
}
func (d DockerLocalRegistry) IsImagePresent(name string) bool {
imageList, err := d.Connection.ImageList(context.Background(), types.ImageListOptions{})
if err != nil {
return false
}
for _, imagex := range imageList {
if len(imagex.RepoTags) == 0 || len(imagex.RepoDigests) == 0 {
continue
}
if imagex.RepoTags[0] == name || (imagex.RepoDigests != nil && strings.HasPrefix(imagex.RepoDigests[0], name)) {
return true
}
}
return false
}
func SetupDockerSocket() (DockerLocalRegistry, string, Docker) {
dockerSocketConn, err := GetDockerConnection()
if err != nil {
klog.V(log.E).ErrorS(err, "Can't get Docker socket")
return DockerLocalRegistry{}, "", Docker{}
}
dockerSock := Docker{Connection: dockerSocketConn}
if err != nil {
klog.V(log.E).ErrorS(err, "error during SetupDockerSocket")
}
_, err = dockerSock.PurgeContainer("", REGISTRY_IMG)
if err != nil {
klog.V(log.E).ErrorS(err, "error during SetupDockerSocket")
}
d := DockerLocalRegistry{Connection: dockerSocketConn}
klog.V(log.I).InfoS("Check if registry image is present", "isPresent", d.IsRegistryImagePresent())
if !d.IsRegistryImagePresent() {
dockerSock.PullImage(REGISTRY_IMG_FULL_TAG)
}
registryID := d.GetRegistryRunningID()
if len(registryID) == 0 {
registryID = d.StartRegistry()
klog.V(log.E).ErrorS(err, "Registry started")
} else {
klog.V(log.I).InfoS("Registry already up and running", "ID", registryID)
}
return d, registryID, dockerSock
}
func DockerTearDown(dlr DockerLocalRegistry) {
if len(dlr.GetRegistryRunningID()) > 0 {
registryID := dlr.GetRegistryRunningID()
dlr.StopAndRemoveContainer(registryID)
} else {
dlr.StopRegistry()
}
}