More pipeline debugging info

This commit is contained in:
Frikky
2024-11-08 16:22:47 +01:00
parent 02b263ebd9
commit f0757416e9
+385 -385
View File
@@ -325,394 +325,397 @@ func cleanupExistingNodes(ctx context.Context) error {
func deployServiceWorkers(image string) {
log.Printf("[DEBUG] Validating deployment of workers as services IF swarmConfig = run (value: %#v)", swarmConfig)
if swarmConfig == "run" || swarmConfig == "swarm" {
ctx := context.Background()
// Looks for and cleans up all existing items in swarm we can't re-use (Shuffle only)
if swarmConfig != "run" && swarmConfig != "swarm" {
log.Printf("[DEBUG] Skipping deployment of workers as services as swarmConfig is not set to run or swarm. Value: %#v", swarmConfig)
return
}
// frikky@debian:~/git/shuffle/functions/onprem/worker$ docker service create --replicas 5 --name shuffle-workers --env SHUFFLE_SWARM_CONFIG=run --publish published=33333,target=33333 ghcr.io/shuffle/shuffle-worker:nightly
// Get a list of network interfaces
interfaces, err := net.Interfaces()
ctx := context.Background()
// Looks for and cleans up all existing items in swarm we can't re-use (Shuffle only)
// frikky@debian:~/git/shuffle/functions/onprem/worker$ docker service create --replicas 5 --name shuffle-workers --env SHUFFLE_SWARM_CONFIG=run --publish published=33333,target=33333 ghcr.io/shuffle/shuffle-worker:nightly
// Get a list of network interfaces
interfaces, err := net.Interfaces()
if err != nil {
log.Printf("[ERROR] Failed to get network interfaces: %s", err)
}
mtu := 1500
if len(dockerSwarmBridgeMTU) == 0 {
mtu, err = strconv.Atoi(dockerSwarmBridgeMTU) // by default
if err != nil {
log.Printf("[ERROR] Failed to get network interfaces: %s", err)
log.Printf("[DEBUG] Failed to convert the default MTU to int: %s. Using 1500 instead. Input: %s", err, dockerSwarmBridgeMTU)
mtu = 1500
}
}
mtu := 1500
if len(dockerSwarmBridgeMTU) == 0 {
mtu, err = strconv.Atoi(dockerSwarmBridgeMTU) // by default
if err != nil {
log.Printf("[DEBUG] Failed to convert the default MTU to int: %s. Using 1500 instead. Input: %s", err, dockerSwarmBridgeMTU)
mtu = 1500
bridgeName := dockerSwarmBridgeInterface
if bridgeName == "" {
bridgeName = "eth0"
}
// Check if there is at least one interface
if len(interfaces) < 2 {
// this assumes that the machine should have at least 2 network
// interfaces. If not, we will use the default MTU.
// interface 1 is the loopback interface
// interface 2 is eth0, The eth0 interface inside a
// Docker container corresponds to the virtual Ethernet
// interface that connects the container to the docker0
log.Printf("[ERROR] Failed to get enough network interfaces")
} else {
// Get the preferred interface
for _, iface := range interfaces {
if strings.Contains(iface.Name, bridgeName) {
targetInterface := iface
mtu = targetInterface.MTU
log.Printf("[INFO] Using MTU %d from interface %s", mtu, targetInterface.Name)
break
}
}
}
bridgeName := dockerSwarmBridgeInterface
if bridgeName == "" {
bridgeName = "eth0"
// Create the network options with the specified MTU
options := make(map[string]string)
options["com.docker.network.driver.mtu"] = fmt.Sprintf("%d", mtu)
ingressOptions := types.NetworkCreate{
Driver: "overlay",
Attachable: false,
Ingress: true,
IPAM: &network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{
network.IPAMConfig{
Subnet: "10.225.225.0/24",
Gateway: "10.225.225.1",
},
},
},
}
_, err = dockercli.NetworkCreate(
ctx,
"ingress",
ingressOptions,
)
if err != nil {
log.Printf("[WARNING] Ingress network may already exist: %s", err)
}
//docker network create --driver=overlay workers
// Specific subnet?
networkName := "shuffle_swarm_executions"
if len(swarmNetworkName) > 0 {
networkName = swarmNetworkName
}
networkCreateOptions := types.NetworkCreate{
Driver: "overlay",
Options: options,
Attachable: true,
Ingress: false,
IPAM: &network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{
network.IPAMConfig{
Subnet: "10.224.224.0/24",
Gateway: "10.224.224.1",
},
},
},
}
_, err = dockercli.NetworkCreate(
ctx,
networkName,
networkCreateOptions,
)
if err != nil {
if strings.Contains(fmt.Sprintf("%s", err), "already exists") {
// Try patching for attachable
} else {
log.Printf("[DEBUG] Failed to create network %s for workers: %s. This is not critical, and containers will still be added", networkName, err)
}
}
defaultNetworkAttach := false
if containerId != "" {
log.Printf("[DEBUG] Should connect orborus container to worker network as it's running in Docker with name %#v!", containerId)
// https://pkg.go.dev/github.com/docker/docker@v20.10.12+incompatible/api/types/network#EndpointSettings
networkConfig := &network.EndpointSettings{}
err := dockercli.NetworkConnect(ctx, networkName, containerId, networkConfig)
if err != nil {
log.Printf("[ERROR] Failed connecting Orborus to docker network %s: %s", networkName, err)
}
// Check if there is at least one interface
if len(interfaces) < 2 {
// this assumes that the machine should have at least 2 network
// interfaces. If not, we will use the default MTU.
// interface 1 is the loopback interface
// interface 2 is eth0, The eth0 interface inside a
// Docker container corresponds to the virtual Ethernet
// interface that connects the container to the docker0
log.Printf("[ERROR] Failed to get enough network interfaces")
} else {
// Get the preferred interface
for _, iface := range interfaces {
if strings.Contains(iface.Name, bridgeName) {
targetInterface := iface
mtu = targetInterface.MTU
log.Printf("[INFO] Using MTU %d from interface %s", mtu, targetInterface.Name)
if len(containerId) == 64 && baseUrl == "http://shuffle-backend:5001" {
log.Printf("[WARNING] Network MAY not work due to backend being %s and container length 64. Will try to attach shuffle_shuffle network", baseUrl)
defaultNetworkAttach = true
}
}
if len(os.Getenv("DOCKER_HOST")) > 0 {
log.Printf("[DEBUG] Deploying docker socket proxy to the network %s as the DOCKER_HOST variable is set", networkName)
containers, err := dockercli.ContainerList(ctx, container.ListOptions{
All: true,
})
if err == nil {
for _, container := range containers {
if strings.Contains(strings.ToLower(container.Image), "docker-socket-proxy") {
networkConfig := &network.EndpointSettings{}
err := dockercli.NetworkConnect(ctx, networkName, container.ID, networkConfig)
if err != nil {
log.Printf("[ERROR] Failed connecting Docker socket proxy to docker network %s: %s", networkName, err)
} else {
log.Printf("[INFO] Attached the docker socket proxy to the execution network")
}
break
}
}
}
// Create the network options with the specified MTU
options := make(map[string]string)
options["com.docker.network.driver.mtu"] = fmt.Sprintf("%d", mtu)
ingressOptions := types.NetworkCreate{
Driver: "overlay",
Attachable: false,
Ingress: true,
IPAM: &network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{
network.IPAMConfig{
Subnet: "10.225.225.0/24",
Gateway: "10.225.225.1",
},
},
},
}
_, err = dockercli.NetworkCreate(
ctx,
"ingress",
ingressOptions,
)
if err != nil {
log.Printf("[WARNING] Ingress network may already exist: %s", err)
}
//docker network create --driver=overlay workers
// Specific subnet?
networkName := "shuffle_swarm_executions"
if len(swarmNetworkName) > 0 {
networkName = swarmNetworkName
}
networkCreateOptions := types.NetworkCreate{
Driver: "overlay",
Options: options,
Attachable: true,
Ingress: false,
IPAM: &network.IPAM{
Driver: "default",
Config: []network.IPAMConfig{
network.IPAMConfig{
Subnet: "10.224.224.0/24",
Gateway: "10.224.224.1",
},
},
},
}
_, err = dockercli.NetworkCreate(
ctx,
networkName,
networkCreateOptions,
)
if err != nil {
if strings.Contains(fmt.Sprintf("%s", err), "already exists") {
// Try patching for attachable
} else {
log.Printf("[DEBUG] Failed to create network %s for workers: %s. This is not critical, and containers will still be added", networkName, err)
}
}
defaultNetworkAttach := false
if containerId != "" {
log.Printf("[DEBUG] Should connect orborus container to worker network as it's running in Docker with name %#v!", containerId)
// https://pkg.go.dev/github.com/docker/docker@v20.10.12+incompatible/api/types/network#EndpointSettings
networkConfig := &network.EndpointSettings{}
err := dockercli.NetworkConnect(ctx, networkName, containerId, networkConfig)
if err != nil {
log.Printf("[ERROR] Failed connecting Orborus to docker network %s: %s", networkName, err)
}
if len(containerId) == 64 && baseUrl == "http://shuffle-backend:5001" {
log.Printf("[WARNING] Network MAY not work due to backend being %s and container length 64. Will try to attach shuffle_shuffle network", baseUrl)
defaultNetworkAttach = true
}
}
if len(os.Getenv("DOCKER_HOST")) > 0 {
log.Printf("[DEBUG] Deploying docker socket proxy to the network %s as the DOCKER_HOST variable is set", networkName)
containers, err := dockercli.ContainerList(ctx, container.ListOptions{
All: true,
})
if err == nil {
for _, container := range containers {
if strings.Contains(strings.ToLower(container.Image), "docker-socket-proxy") {
networkConfig := &network.EndpointSettings{}
err := dockercli.NetworkConnect(ctx, networkName, container.ID, networkConfig)
if err != nil {
log.Printf("[ERROR] Failed connecting Docker socket proxy to docker network %s: %s", networkName, err)
} else {
log.Printf("[INFO] Attached the docker socket proxy to the execution network")
}
break
}
}
} else {
log.Printf("[ERROR] Failed listing containers when deploying socket proxy on swarm: %s", err)
}
//} else {
// log.Printf("[ERROR] Failed listing and finding the right image for docker socket proxy: %s", err)
//}
}
replicas := uint64(1)
scaleReplicas := os.Getenv("SHUFFLE_SCALE_REPLICAS")
if len(scaleReplicas) > 0 {
tmpInt, err := strconv.Atoi(scaleReplicas)
if err != nil {
log.Printf("[ERROR] %s is not a valid number for replication", scaleReplicas)
} else {
replicas = uint64(tmpInt)
}
log.Printf("[DEBUG] SHUFFLE_SCALE_REPLICAS set to value %#v. Trying to overwrite default (%d/node)", scaleReplicas, replicas)
}
innerContainerName := fmt.Sprintf("shuffle-workers")
cnt, err := findActiveSwarmNodes()
if err != nil {
log.Printf("[ERROR] Failed to find active swarm nodes: %s. Defaulting to 1", err)
}
nodeCount := uint64(1)
if cnt > 0 {
nodeCount = uint64(cnt)
}
appReplicas := os.Getenv("SHUFFLE_APP_REPLICAS")
appReplicaCnt := 1
if len(appReplicas) > 0 {
newCnt, err := strconv.Atoi(appReplicas)
if err != nil {
log.Printf("[ERROR] %s is not a valid number for SHUFFLE_APP_REPLICAS", appReplicas)
} else {
appReplicaCnt = newCnt
}
}
log.Printf("[DEBUG] Found %d node(s) to replicate over. Defaulting to 1 IF we can't auto-discover them.", cnt)
replicatedJobs := uint64(replicas * nodeCount)
log.Printf("[DEBUG] Deploying %d container(s) for worker with swarm to each node. Service name: %s. Image: %s", replicas, innerContainerName, image)
if timezone == "" {
timezone = "Europe/Amsterdam"
}
// FIXME: May not need ingress ports. Could use internal services and DNS of swarm itself
// https://github.com/moby/moby/blob/e2f740de442bac52b280bc485a3ca5b31567d938/api/types/swarm/service.go#L46
serviceSpec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: innerContainerName,
Labels: map[string]string{},
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &replicatedJobs,
},
},
Networks: []swarm.NetworkAttachmentConfig{
swarm.NetworkAttachmentConfig{
Target: networkName,
},
swarm.NetworkAttachmentConfig{
Target: "ingress",
},
},
EndpointSpec: &swarm.EndpointSpec{
Mode: "vip",
Ports: []swarm.PortConfig{
swarm.PortConfig{
Protocol: swarm.PortConfigProtocolTCP,
PublishMode: swarm.PortConfigPublishModeIngress,
Name: "worker-port",
PublishedPort: 33333,
TargetPort: 33333,
},
},
},
TaskTemplate: swarm.TaskSpec{
Resources: &swarm.ResourceRequirements{
Reservations: &swarm.Resources{},
},
LogDriver: &swarm.Driver{
Name: "json-file",
Options: map[string]string{
"max-size": "10m",
},
},
ContainerSpec: &swarm.ContainerSpec{
Image: image,
Env: []string{
fmt.Sprintf("SHUFFLE_SWARM_CONFIG=%s", os.Getenv("SHUFFLE_SWARM_CONFIG")),
fmt.Sprintf("SHUFFLE_SWARM_NETWORK_NAME=%s", networkName),
fmt.Sprintf("SHUFFLE_APP_REPLICAS=%d", appReplicaCnt),
fmt.Sprintf("SHUFFLE_LOGS_DISABLED=%s", os.Getenv("SHUFFLE_LOGS_DISABLED")),
fmt.Sprintf("DEBUG_MEMORY=%s", os.Getenv("DEBUG_MEMORY")),
fmt.Sprintf("SHUFFLE_APP_SDK_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_SDK_TIMEOUT")),
fmt.Sprintf("SHUFFLE_MAX_SWARM_NODES=%d", os.Getenv("SHUFFLE_MAX_SWARM_NODES")),
fmt.Sprintf("SHUFFLE_BASE_IMAGE_NAME=%s", os.Getenv("SHUFFLE_BASE_IMAGE_NAME")),
fmt.Sprintf("SHUFFLE_APP_REQUEST_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_REQUEST_TIMEOUT")),
},
//Hosts: []string{
// innerContainerName,
//},
},
RestartPolicy: &swarm.RestartPolicy{
Condition: swarm.RestartPolicyConditionOnFailure,
},
Placement: &swarm.Placement{
MaxReplicas: replicas,
},
},
}
if defaultNetworkAttach == true || strings.ToLower(os.Getenv("SHUFFLE_DEFAULT_NETWORK_ATTACH")) == "true" {
targetName := "shuffle_shuffle"
log.Printf("[DEBUG] Adding network attach for network %s to worker in swarm", targetName)
serviceSpec.Networks = append(serviceSpec.Networks, swarm.NetworkAttachmentConfig{
Target: targetName,
})
// FIXM: Remove this if deployment fails?
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_SWARM_OTHER_NETWORK=%s", targetName))
}
if dockerApiVersion != "" {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
}
if len(os.Getenv("SHUFFLE_SCALE_REPLICAS")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_SCALE_REPLICAS=%s", os.Getenv("SHUFFLE_SCALE_REPLICAS")))
}
if len(os.Getenv("SHUFFLE_MEMCACHED")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_MEMCACHED=%s", os.Getenv("SHUFFLE_MEMCACHED")))
}
if strings.ToLower(os.Getenv("SHUFFLE_PASS_WORKER_PROXY")) == "true" {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("HTTP_PROXY=%s", os.Getenv("HTTP_PROXY")))
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("HTTPS_PROXY=%s", os.Getenv("HTTPS_PROXY")))
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("NO_PROXY=%s", os.Getenv("NO_PROXY")))
}
if len(workerServerUrl) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_WORKER_SERVER_URL=%s", os.Getenv("SHUFFLE_WORKER_SERVER_URL")))
}
// Handles backend
if len(os.Getenv("BASE_URL")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("BASE_URL=%s", os.Getenv("BASE_URL")))
}
if len(os.Getenv("SHUFFLE_CLOUDRUN_URL")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_CLOUDRUN_URL=%s", os.Getenv("SHUFFLE_CLOUDRUN_URL")))
}
if len(os.Getenv("SHUFFLE_AUTO_IMAGE_DOWNLOAD")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_AUTO_IMAGE_DOWNLOAD=%s", os.Getenv("SHUFFLE_AUTO_IMAGE_DOWNLOAD")))
}
if len(os.Getenv("DOCKER_HOST")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("DOCKER_HOST=%s", os.Getenv("DOCKER_HOST")))
} else {
if runtime.GOOS == "windows" {
serviceSpec.TaskTemplate.ContainerSpec.Mounts = []mount.Mount{
mount.Mount{
Source: `\\.\pipe\docker_engine`,
Target: `\\.\pipe\docker_engine`,
Type: mount.TypeBind,
},
}
} else {
serviceSpec.TaskTemplate.ContainerSpec.Mounts = []mount.Mount{
mount.Mount{
Source: "/var/run/docker.sock",
Target: "/var/run/docker.sock",
Type: mount.TypeBind,
},
}
}
log.Printf("[ERROR] Failed listing containers when deploying socket proxy on swarm: %s", err)
}
//} else {
// log.Printf("[ERROR] Failed listing and finding the right image for docker socket proxy: %s", err)
//}
}
// Look for SHUFFLE_VOLUME_BINDS
if len(os.Getenv("SHUFFLE_VOLUME_BINDS")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_VOLUME_BINDS=%s", os.Getenv("SHUFFLE_VOLUME_BINDS")))
}
overrideHttpProxy := os.Getenv("SHUFFLE_INTERNAL_HTTP_PROXY")
overrideHttpsProxy := os.Getenv("SHUFFLE_INTERNAL_HTTPS_PROXY")
if len(overrideHttpProxy) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_INTERNAL_HTTP_PROXY=%s", overrideHttpProxy))
}
if len(overrideHttpsProxy) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_INTERNAL_HTTPS_PROXY=%s", overrideHttpsProxy))
}
serviceOptions := types.ServiceCreateOptions{}
_, err = dockercli.ServiceCreate(
ctx,
serviceSpec,
serviceOptions,
)
// Force deploy if it's not disabled
deployTenzirNode()
if err == nil {
log.Printf("[DEBUG] Successfully deployed workers with %d replica(s) on %d node(s)", replicas, cnt)
//time.Sleep(time.Duration(10) * time.Second)
//log.Printf("[DEBUG] Servicecreate request: %#v %#v", service, err)
replicas := uint64(1)
scaleReplicas := os.Getenv("SHUFFLE_SCALE_REPLICAS")
if len(scaleReplicas) > 0 {
tmpInt, err := strconv.Atoi(scaleReplicas)
if err != nil {
log.Printf("[ERROR] %s is not a valid number for replication", scaleReplicas)
} else {
if !strings.Contains(fmt.Sprintf("%s", err), "Already Exists") && !strings.Contains(fmt.Sprintf("%s", err), "is already in use by service") {
log.Printf("[ERROR] Failed making service: %s", err)
} else {
log.Printf("[WARNING] Failed deploying workers: %s", err)
if len(serviceSpec.Networks) > 1 {
serviceSpec.Networks = []swarm.NetworkAttachmentConfig{
swarm.NetworkAttachmentConfig{
Target: "shuffle_shuffle",
},
}
_, _ = dockercli.ServiceCreate(
ctx,
serviceSpec,
serviceOptions,
)
}
}
replicas = uint64(tmpInt)
}
log.Printf("[DEBUG] SHUFFLE_SCALE_REPLICAS set to value %#v. Trying to overwrite default (%d/node)", scaleReplicas, replicas)
}
innerContainerName := fmt.Sprintf("shuffle-workers")
cnt, err := findActiveSwarmNodes()
if err != nil {
log.Printf("[ERROR] Failed to find active swarm nodes: %s. Defaulting to 1", err)
}
nodeCount := uint64(1)
if cnt > 0 {
nodeCount = uint64(cnt)
}
appReplicas := os.Getenv("SHUFFLE_APP_REPLICAS")
appReplicaCnt := 1
if len(appReplicas) > 0 {
newCnt, err := strconv.Atoi(appReplicas)
if err != nil {
log.Printf("[ERROR] %s is not a valid number for SHUFFLE_APP_REPLICAS", appReplicas)
} else {
appReplicaCnt = newCnt
}
}
log.Printf("[DEBUG] Found %d node(s) to replicate over. Defaulting to 1 IF we can't auto-discover them.", cnt)
replicatedJobs := uint64(replicas * nodeCount)
log.Printf("[DEBUG] Deploying %d container(s) for worker with swarm to each node. Service name: %s. Image: %s", replicas, innerContainerName, image)
if timezone == "" {
timezone = "Europe/Amsterdam"
}
// FIXME: May not need ingress ports. Could use internal services and DNS of swarm itself
// https://github.com/moby/moby/blob/e2f740de442bac52b280bc485a3ca5b31567d938/api/types/swarm/service.go#L46
serviceSpec := swarm.ServiceSpec{
Annotations: swarm.Annotations{
Name: innerContainerName,
Labels: map[string]string{},
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &replicatedJobs,
},
},
Networks: []swarm.NetworkAttachmentConfig{
swarm.NetworkAttachmentConfig{
Target: networkName,
},
swarm.NetworkAttachmentConfig{
Target: "ingress",
},
},
EndpointSpec: &swarm.EndpointSpec{
Mode: "vip",
Ports: []swarm.PortConfig{
swarm.PortConfig{
Protocol: swarm.PortConfigProtocolTCP,
PublishMode: swarm.PortConfigPublishModeIngress,
Name: "worker-port",
PublishedPort: 33333,
TargetPort: 33333,
},
},
},
TaskTemplate: swarm.TaskSpec{
Resources: &swarm.ResourceRequirements{
Reservations: &swarm.Resources{},
},
LogDriver: &swarm.Driver{
Name: "json-file",
Options: map[string]string{
"max-size": "10m",
},
},
ContainerSpec: &swarm.ContainerSpec{
Image: image,
Env: []string{
fmt.Sprintf("SHUFFLE_SWARM_CONFIG=%s", os.Getenv("SHUFFLE_SWARM_CONFIG")),
fmt.Sprintf("SHUFFLE_SWARM_NETWORK_NAME=%s", networkName),
fmt.Sprintf("SHUFFLE_APP_REPLICAS=%d", appReplicaCnt),
fmt.Sprintf("SHUFFLE_LOGS_DISABLED=%s", os.Getenv("SHUFFLE_LOGS_DISABLED")),
fmt.Sprintf("DEBUG_MEMORY=%s", os.Getenv("DEBUG_MEMORY")),
fmt.Sprintf("SHUFFLE_APP_SDK_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_SDK_TIMEOUT")),
fmt.Sprintf("SHUFFLE_MAX_SWARM_NODES=%d", os.Getenv("SHUFFLE_MAX_SWARM_NODES")),
fmt.Sprintf("SHUFFLE_BASE_IMAGE_NAME=%s", os.Getenv("SHUFFLE_BASE_IMAGE_NAME")),
fmt.Sprintf("SHUFFLE_APP_REQUEST_TIMEOUT=%s", os.Getenv("SHUFFLE_APP_REQUEST_TIMEOUT")),
},
//Hosts: []string{
// innerContainerName,
//},
},
RestartPolicy: &swarm.RestartPolicy{
Condition: swarm.RestartPolicyConditionOnFailure,
},
Placement: &swarm.Placement{
MaxReplicas: replicas,
},
},
}
if defaultNetworkAttach == true || strings.ToLower(os.Getenv("SHUFFLE_DEFAULT_NETWORK_ATTACH")) == "true" {
targetName := "shuffle_shuffle"
log.Printf("[DEBUG] Adding network attach for network %s to worker in swarm", targetName)
serviceSpec.Networks = append(serviceSpec.Networks, swarm.NetworkAttachmentConfig{
Target: targetName,
})
// FIXM: Remove this if deployment fails?
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_SWARM_OTHER_NETWORK=%s", targetName))
}
if dockerApiVersion != "" {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("DOCKER_API_VERSION=%s", dockerApiVersion))
}
if len(os.Getenv("SHUFFLE_SCALE_REPLICAS")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_SCALE_REPLICAS=%s", os.Getenv("SHUFFLE_SCALE_REPLICAS")))
}
if len(os.Getenv("SHUFFLE_MEMCACHED")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_MEMCACHED=%s", os.Getenv("SHUFFLE_MEMCACHED")))
}
if strings.ToLower(os.Getenv("SHUFFLE_PASS_WORKER_PROXY")) == "true" {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("HTTP_PROXY=%s", os.Getenv("HTTP_PROXY")))
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("HTTPS_PROXY=%s", os.Getenv("HTTPS_PROXY")))
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("NO_PROXY=%s", os.Getenv("NO_PROXY")))
}
if len(workerServerUrl) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_WORKER_SERVER_URL=%s", os.Getenv("SHUFFLE_WORKER_SERVER_URL")))
}
// Handles backend
if len(os.Getenv("BASE_URL")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("BASE_URL=%s", os.Getenv("BASE_URL")))
}
if len(os.Getenv("SHUFFLE_CLOUDRUN_URL")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_CLOUDRUN_URL=%s", os.Getenv("SHUFFLE_CLOUDRUN_URL")))
}
if len(os.Getenv("SHUFFLE_AUTO_IMAGE_DOWNLOAD")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_AUTO_IMAGE_DOWNLOAD=%s", os.Getenv("SHUFFLE_AUTO_IMAGE_DOWNLOAD")))
}
if len(os.Getenv("DOCKER_HOST")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("DOCKER_HOST=%s", os.Getenv("DOCKER_HOST")))
} else {
if runtime.GOOS == "windows" {
serviceSpec.TaskTemplate.ContainerSpec.Mounts = []mount.Mount{
mount.Mount{
Source: `\\.\pipe\docker_engine`,
Target: `\\.\pipe\docker_engine`,
Type: mount.TypeBind,
},
}
} else {
serviceSpec.TaskTemplate.ContainerSpec.Mounts = []mount.Mount{
mount.Mount{
Source: "/var/run/docker.sock",
Target: "/var/run/docker.sock",
Type: mount.TypeBind,
},
}
}
}
// Look for SHUFFLE_VOLUME_BINDS
if len(os.Getenv("SHUFFLE_VOLUME_BINDS")) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_VOLUME_BINDS=%s", os.Getenv("SHUFFLE_VOLUME_BINDS")))
}
overrideHttpProxy := os.Getenv("SHUFFLE_INTERNAL_HTTP_PROXY")
overrideHttpsProxy := os.Getenv("SHUFFLE_INTERNAL_HTTPS_PROXY")
if len(overrideHttpProxy) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_INTERNAL_HTTP_PROXY=%s", overrideHttpProxy))
}
if len(overrideHttpsProxy) > 0 {
serviceSpec.TaskTemplate.ContainerSpec.Env = append(serviceSpec.TaskTemplate.ContainerSpec.Env, fmt.Sprintf("SHUFFLE_INTERNAL_HTTPS_PROXY=%s", overrideHttpsProxy))
}
serviceOptions := types.ServiceCreateOptions{}
_, err = dockercli.ServiceCreate(
ctx,
serviceSpec,
serviceOptions,
)
// Force deploy if it's not disabled
deployTenzirNode()
if err == nil {
log.Printf("[DEBUG] Successfully deployed workers with %d replica(s) on %d node(s)", replicas, cnt)
//time.Sleep(time.Duration(10) * time.Second)
//log.Printf("[DEBUG] Servicecreate request: %#v %#v", service, err)
} else {
if !strings.Contains(fmt.Sprintf("%s", err), "Already Exists") && !strings.Contains(fmt.Sprintf("%s", err), "is already in use by service") {
log.Printf("[ERROR] Failed making service: %s", err)
} else {
log.Printf("[WARNING] Failed deploying workers: %s", err)
if len(serviceSpec.Networks) > 1 {
serviceSpec.Networks = []swarm.NetworkAttachmentConfig{
swarm.NetworkAttachmentConfig{
Target: "shuffle_shuffle",
},
}
_, _ = dockercli.ServiceCreate(
ctx,
serviceSpec,
serviceOptions,
)
}
}
}
}
@@ -1910,7 +1913,7 @@ func main() {
pipelineUrl = "http://localhost:5160"
// Find the IP in baseUrl. Base format is http://<ip>:<port>
if baseUrl != "" {
if baseUrl != "" && !strings.Contains(baseUrl, "shuffle") && !strings.Contains(baseUrl, "localhost") && !strings.Contains(baseUrl, "run.app") {
urlSplit := strings.Split(baseUrl, "://")
if len(urlSplit) > 1 {
// Find the IP
@@ -1921,6 +1924,10 @@ func main() {
}
}
if len(containerId) > 0 {
pipelineUrl = "http://tenzir-node:5160"
}
log.Printf("[WARNING] SHUFFLE_PIPELINE_URL not set, falling back to default URL: %s. If BASE_URL is set, we use the external IP for that", pipelineUrl)
os.Setenv("SHUFFLE_PIPELINE_URL", pipelineUrl)
}
@@ -2605,7 +2612,7 @@ func deployTenzirNode() error {
// Check if image exists
_, _, err := dockercli.ImageInspectWithRaw(ctx, imageName)
if dockerclient.IsErrNotFound(err) {
log.Printf("[DEBUG] Pulling image %s", imageName)
log.Printf("[DEBUG] Pulling image %s. This may take a while.", imageName)
pullOptions := image.PullOptions{}
out, err := dockercli.ImagePull(ctx, imageName, pullOptions)
if err != nil {
@@ -2671,6 +2678,7 @@ func createAndStartTenzirNode(ctx context.Context, containerName, imageName stri
// Ensure restart policy is there
config := &container.Config{
Hostname: containerName,
Cmd: []string{"--commands=web server --mode=dev --bind=0.0.0.0"},
Image: imageName,
Healthcheck: healthconfig,
@@ -2768,9 +2776,6 @@ func createAndStartTenzirNode(ctx context.Context, containerName, imageName stri
if isKubernetes != "true" {
hostConfig.NetworkMode = container.NetworkMode(fmt.Sprintf("container:%s", containerId))
if strings.ToLower(cleanupEnv) != "false" {
hostConfig.AutoRemove = true
}
}
_, err := dockercli.ContainerCreate(ctx, config, hostConfig, networkingConfig, nil, containerName)
@@ -2858,9 +2863,6 @@ func checkTenzirNode() error {
return errors.New("Pipelines are disabled by user with SHUFFLE_SKIP_PIPELINES")
}
retries := 1
//retryInterval := 3 * time.Second
url := fmt.Sprintf("%s/api/v0/ping", pipelineUrl)
forwardMethod := "POST"
@@ -2873,16 +2875,14 @@ func checkTenzirNode() error {
return err
}
for i := 0; i < retries; i++ {
resp, err := client.Do(req)
if err == nil && resp.StatusCode == http.StatusOK {
return nil
}
//time.Sleep(retryInterval)
resp, err := client.Do(req)
if err == nil && resp.StatusCode == http.StatusOK {
return nil
}
return fmt.Errorf("tenzir node is not available")
log.Printf("[DEBUG] Failed to verify Tenzir node on %s: %s", url, err)
return fmt.Errorf("Tenzir node is not available")
}
func createPipeline(command, identifier string) (string, error) {