require "sct_core" require "shell/ClassLevelInheritableAttributes" module Shell class Docker include ClassLevelInheritableAttributes inheritable_attributes :image, :is_private_registry, :entrypoint, :volumes, :ports, :extra_arguments, :env_variables @image = nil @is_private_registry = false @entrypoint = nil @volumes = {} @ports = {} @user_group = [] @extra_arguments = {} @env_variables = {} ### # 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) self.add_extra_argument(cli_arguments) 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.check_for_image && @is_private_registry unless self.login_to_private_registry raise RuntimeError, "Could not authenticate to GCR (" + $?.exitstatus + ")" end end self.run_command end ### # The image for this Docker command ### def self.set_image(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.set_pwd_as_volume(volume_path) pwd = `pwd -P` if SctCore::Helper.operatingSystem == SctCore::Helper::WINDOWS pwd=SctCore::Helper.convertWSLToWindowsPath(pwd) end add_volume(pwd, volume_path) end ### # Add an extra volume in the container ### def self.add_volume(local_path, volume_path) @volumes[local_path] = volume_path end ### # Add a port mapping for the container ### def self.map_port(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.set_current_user_and_group @user_group = [] @user_group << `id -u` @user_group << `id -g` end ### # Set the entrypoint for the command in the container ### def self.set_entrypoint(entrypoint) @entrypoint=entrypoint end ### # Add extra arguments to be configured for the container ### def self.add_extra_argument(argument, value=nil) argument = String(argument) if value value = String(value) end self.extra_arguments[argument] = value end ### # Set environment variables for the container ### def self.set_environment_variables(env_variables) @env_variables = env_variables end ### # Check if the image is already present in the system ### def self.check_for_image 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.login_to_private_registry `docker login -u oauth2accesstoken -p "$(gcloud auth application-default print-access-token)" https://eu.gcr.io &> /dev/null` return $?.success? end ### # Run the command ### def self.run_command command = self.compile_command SctCore::CommandExecutor.execute(command: command, print_all: true, suppress_output: false) end ### # Compile the command with all options ### def self.compile_command # Basic docker run command command = self.add_to_command_string("" , "docker run --rm -it") # Attach environment variables if @env_variables @env_variables.each do |key, value| if value && !value.empty? command = self.add_to_command_string(command, "-e " + key+"="+value) else command = self.add_to_command_string("-e " + key, value) end end end # Attach configured volumes if @volumes @volumes.each do |local_path, container_path| command = self.add_to_command_string(command, "--volume " + local_path +":"+ container_path) end end # Map configured ports if @ports @ports.each do |external_port, container_port| command = self.add_to_command_string(command, "-p " + external_port +":"+ container_port) end end if @user_group command = self.add_to_command_string(command, "--user "+ String(@user_group.shift) +":"+ String(@user_group.shift)) end # Add image to command command = self.add_to_command_string(command, @image) if @entrypoint command = self.add_to_command_string(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.add_to_command_string(command, argument+"="+value) else command = self.add_to_command_string(command, argument) end end end return command end ### # Append a part to the command string and remove any unwanted characters ### def self.add_to_command_string(command_string, append) return command_string + append.gsub(/\r?\n/, "") + " " end end end