require "sct/ClassLevelInheritableAttributes" module Sct class Docker include ClassLevelInheritableAttributes inheritable_attributes :image, :is_private_registry, :entrypoint, :volumes, :ports, :extra_arguments @image = nil @is_private_registry = false @entrypoint = nil @volumes = {} @ports = {} @user_group = [] @extra_arguments = {} ### # The Docker command configuration. This has to be able to execute the command properly ### def self.config # Run some initialization commands end ### # Execute the configured command ### def self.exec(cli_arguments) cli_arguments.each do | argument | self.addExtraArgument(argument) end self.config() # Check if the basic variables are set if !@image || @image.empty? raise LoadError, "The required image is not defined for this command" end if !self.checkForImage() && @is_private_registry if !self.loginToPrivateRegistry() raise RuntimeError, "Could not authenticate to GCR (" + $?.exitstatus + ")" end end self.runCommand() end ### # The image for this Docker command ### def self.setImage(image, is_private_registry=false) @image = image @is_private_registry = is_private_registry end ### # Set the current PWD as a volume on the specified path in the container ### def self.setPwdAsVolume(volume_path) pwd = `pwd -P` if Sct::Config.operatingSystem == Sct::Config::WINDOWS pwd=Sct::Config.convertWSLToWindowsPath(pwd) end addVolume(pwd, volume_path) end ### # Add an extra volume in the container ### def self.addVolume(localPath, volume_path) @volumes[localPath] = volume_path end ### # Add a port mapping for the container ### def self.mapPort(external_port, container_port = nil) external_port=String(external_port) container_port=String(container_port) if container_port.empty? container_port = external_port end @ports[external_port] = container_port end ### # Set the current user and group in the container ### def self.setCurrentUserAndGroup @user_group = [] @user_group << `id -u` @user_group << `id -g` end ### # Set the entrypoint for the command in the container ### def self.setEntrypoint(entrypoint) @entrypoint=entrypoint end ### # Add extra arguments to be configured for the container ### def self.addExtraArgument(argument, value=nil) argument = String(argument) if value value = String(value) end self.extra_arguments[argument] = value end ### # Check if the image is already present in the system ### def self.checkForImage image_list=`docker images -q #{@image} 2> /dev/null` return image_list && !image_list.empty? end ### # Login to the private container registry with the cloud credentials ### def self.loginToPrivateRegistry `docker login -u oauth2accesstoken -p "$(gcloud auth application-default print-access-token)" https://eu.gcr.io &>2` return $?.success? end ### # Run the command ### def self.runCommand() command = self.compileCommand() system(command) return $?.success? end ### # Compile the command with all options ### def self.compileCommand() # Basic docker run command command = self.addToCommandString("" , "docker run --rm -it") # Attach configured volumes if @volumes @volumes.each do |local_path, container_path| command = self.addToCommandString(command, "--volume " + local_path +":"+ container_path) end end # Map configured ports if @ports @ports.each do |external_port, container_port| command = self.addToCommandString(command, "-p " + external_port +":"+ container_port) end end if @user_group command = self.addToCommandString(command, "--user "+ String(@user_group.shift()) +":"+ String(@user_group.shift())) end # Add image to command command = self.addToCommandString(command, @image) if @entrypoint command = self.addToCommandString(command, String(@entrypoint)) end # Append arguments and options to command if @extra_arguments @extra_arguments.each do |argument, value| if value && !value.empty? command = self.addToCommandString(command, argument+"="+value) else command = self.addToCommandString(command, argument) end end end return command end ### # Append a part to the command string and remove any unwanted characters ### def self.addToCommandString(command_string, append) return command_string + append.gsub(/\r?\n/, "") + " " end end end