diff --git a/HISTORY.rst b/HISTORY.rst new file mode 100644 index 0000000..6f2ac5d --- /dev/null +++ b/HISTORY.rst @@ -0,0 +1,22 @@ + +.. :changelog: + +2020.1.0 (2020-06-24) ++++++++++++++++++++++ + +- Add new available resen-core: 2020.1.0 +- bug fixed when importing a bucket: now tar files of mounted paths are removed after a successful import. +- fixed bug causing enabling sudo access for user jovyan failed + +2019.1.1 (2019-12-10) ++++++++++++++++++++++ + +- Raise exceptions added when local storage not found +- Add detection of resen running on a windows system +- if docker toolbox, change path to be the docker VM path instead of the host machine path +- find a port that is available + +2019.1.0 (2019-11-24) ++++++++++++++++++++++ + +- Initial release. diff --git a/README.rst b/README.rst index 571d759..0e16015 100644 --- a/README.rst +++ b/README.rst @@ -18,7 +18,7 @@ Resen requires both python 3 and docker to be installed. 1. Install `Python 3 `_ 2. Install `docker `_ -3. Install Resen with pip ``pip install git+https://github.com/EarthCubeInGeo/resen.git@v2019.1.1`` +3. Install Resen with pip ``pip install git+https://github.com/EarthCubeInGeo/resen.git@v2020.1.0`` Please refer to the `installation documentation `_ for more detailed instructions. diff --git a/docs/index.rst b/docs/index.rst index f9ee7c4..366aca5 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,3 +9,7 @@ Contents installation/index usage +Changelog +--------- + +.. include:: ../HISTORY.rst diff --git a/docs/installation/installation.general.rst b/docs/installation/installation.general.rst index 1b0b303..a3fa233 100644 --- a/docs/installation/installation.general.rst +++ b/docs/installation/installation.general.rst @@ -33,4 +33,4 @@ Resen Install Resen from a python 3 environment using ``pip``:: - pip install git+https://github.com/EarthCubeInGeo/resen.git@v2019.1.1 + pip install git+https://github.com/EarthCubeInGeo/resen.git@v2020.1.0 diff --git a/docs/usage.rst b/docs/usage.rst index 32695b1..71d5881 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -12,7 +12,7 @@ This will open the resen tool:: | / _|\__ \ _|| .` | |_|_\___|___/___|_|\_| - Resen 2019.1.0 -- Reproducible Software Environment + Resen 2020.1.0 -- Reproducible Software Environment [resen] >>> @@ -54,8 +54,8 @@ Setup a New Bucket Next, the user is asked to specify the version of resen-core to use:: Please choose a version of resen-core. - Available versions: 2019.1.0 - >>> Select a version: 2019.1.0 + Available versions: 2019.1.0, 2020.1.0 + >>> Select a version: 2020.1.0 Optionally, one may then specify a local directory to mount into the bucket at ``/home/jovyan/mount``:: @@ -88,7 +88,7 @@ Setup a New Bucket amber ===== - Resen-core Version: 2019.1.0 + Resen-core Version: 2020.1.0 Status: running Jupyter Token: e7a11fc1ea42a445807b4e24146b9908e1abff82bacbf6f2 Jupyter Port: 9002 @@ -110,7 +110,7 @@ Work with a Bucket [resen] >>> list Bucket Name Docker Image Status - amber 2019.1.0 running + amber 2020.1.0 running If a bucket is running, it will consume system resources accordingly. @@ -122,7 +122,7 @@ Work with a Bucket [resen] >>> list Bucket Name Docker Image Status - amber 2019.1.0 exited + amber 2020.1.0 exited The bucket will still exist and can be restarted at any time, even after quitting and restarting resen. @@ -134,7 +134,7 @@ Work with a Bucket [resen] >>> status Bucket Name Docker Image Status - amber 2019.1.0 running + amber 2020.1.0 running 4. Export bucket ``amber``:: @@ -208,6 +208,11 @@ Work with a Bucket ...starting jupyterlab... Jupyter lab can be accessed in a browser at: http://localhost:9003/?token=70532767bab0ddc4febe2790efaaf974961e961e78e6025a +Sudo-enabled buckets +-------------------- + +When starting a bucket with resen, `sudo` is enabled for the jovyan user to allow special installation and configuration +where root security privileges are needed. The password for running `sudo` commands with user jovyan is: `ganimede`. Remove a Bucket --------------- diff --git a/resen/DockerHelper.py b/resen/DockerHelper.py index c41b7d1..1c0b9d3 100644 --- a/resen/DockerHelper.py +++ b/resen/DockerHelper.py @@ -104,12 +104,12 @@ def stop_container(self,bucket): return container.status - def execute_command(self,bucket,command,user='jovyan',detach=True): + def execute_command(self,bucket,command,user='jovyan',detach=True,tty=False): ''' Execute a command in a container. Returns the exit code and output ''' container = self.docker.containers.get(bucket['container']) - result = container.exec_run(command,user=user,detach=detach) + result = container.exec_run(command,user=user,detach=detach,tty=tty) return result.exit_code, result.output diff --git a/resen/Resen.py b/resen/Resen.py index d239046..9c48b29 100644 --- a/resen/Resen.py +++ b/resen/Resen.py @@ -461,7 +461,7 @@ def stop_bucket(self,bucket_name): return - def execute_command(self,bucket_name,command,user='jovyan',detach=True): + def execute_command(self,bucket_name,command,user='jovyan',detach=True,tty=False): ''' Execute a command in the bucket. Returns the exit code and output form the command, if applicable (if not detached?). ''' @@ -474,7 +474,7 @@ def execute_command(self,bucket_name,command,user='jovyan',detach=True): raise RuntimeError('Bucket %s is not running!' % (bucket['name'])) # execute command - result = self.dockerhelper.execute_command(bucket,command,user=user,detach=detach) + result = self.dockerhelper.execute_command(bucket,command,user=user,detach=detach,tty=tty) code, output = result if (detach and code is not None) or (not detach and code!=0): raise RuntimeError('Failed to execute command %s' % (command)) @@ -487,7 +487,7 @@ def set_sudo(self, bucket_name, password='ganimede'): Add jovyan user to sudoers ''' cmd = "bash -cl 'echo \"jovyan:{}\" | chpasswd && usermod -aG sudo jovyan && sed --in-place \"s/^#\s*\(%sudo\s\+ALL=(ALL:ALL)\s\+ALL\)/\\1/\" /etc/sudoers'".format(password) - self.execute_command(bucket_name, cmd, user='root') + self.execute_command(bucket_name,cmd,user='root',detach=False,tty=True) return @@ -726,6 +726,8 @@ def import_bucket(self,bucket_name,filename,extract_dir=None,img_repo=None,img_t with tarfile.open(str(extract_dir.joinpath(mount[0]))) as tar: tar.extractall(path=str(extract_dir)) local = extract_dir.joinpath(tar.getnames()[0]) + # remove mount tar file + os.remove(str(extract_dir.joinpath(mount[0]))) # add mount to bucket with original container path self.add_storage(bucket_name,str(local),mount[1],permissions=mount[2]) @@ -835,7 +837,13 @@ def __get_valid_cores(self): # and if that fails, fallback to hardcoded list return [{"version":"2019.1.0","repo":"resen-core","org":"earthcubeingeo", "image_id":'sha256:5300c6652851f35d2fabf866491143f471a7e121998fba27a8dff6b3c064af35', - "repodigest":'sha256:a8ff4a65aa6fee6b63f52290c661501f6de5bf4c1f05202ac8823583eaad4296'},] + "repodigest":'sha256:a8ff4a65aa6fee6b63f52290c661501f6de5bf4c1f05202ac8823583eaad4296'}, + {"version":"2020.1.0","repo":"resen-core","org":"earthcubeingeo", + "image_id":'sha256:b1f1c9013924c95f678a0aa7403e343cc2ee103f438b1a237193f091170ba077', + "repodigest":'sha256:7bf4e28cf06e40b0e12cb0474232d6d3b520ec1a8c2d361d83fc0cb97083989c'}, + ] + + def _get_config_dir(self): diff --git a/resen/__init__.py b/resen/__init__.py index 78f73b3..404aabe 100644 --- a/resen/__init__.py +++ b/resen/__init__.py @@ -1,3 +1,3 @@ -__version__ = '2019.1.1' +__version__ = '2020.1.0' from .Resen import Resen diff --git a/resen/resencmd.py b/resen/resencmd.py index 41808e5..7743f2e 100644 --- a/resen/resencmd.py +++ b/resen/resencmd.py @@ -260,7 +260,7 @@ def do_import(self,args): resen_home_dir = self.program.resen_home_dir default_import = os.path.join(resen_home_dir,bucket_name) print("The default directory to extract the bucket metadata and mounts to is {}.".format(default_import)) - rsp = self.get_yn(">>> Would you like to specify and alternate directory? (y/n): ") + rsp = self.get_yn(">>> Would you like to specify an alternate directory? (y/n): ") if rsp=='y': while True: extract_dir = input('>>> Enter path to directory: ') diff --git a/setup.py b/setup.py index cece08f..5a2d22e 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # https://packaging.python.org/en/latest/single_source_version.html - version='2019.1.1', #TODO: parse this from resen/__init__.py + version='2020.1.0', #TODO: parse this from resen/__init__.py description='A python package for watching, copying, and transporting files around.', long_description=long_description,