Skip to content

Commit

Permalink
Merge pull request #400 from arista-eosplus/release-2.0.1
Browse files Browse the repository at this point in the history
Release 2.0.1
  • Loading branch information
dlobato authored Sep 4, 2023
2 parents 8058dcc + b28198b commit f079163
Show file tree
Hide file tree
Showing 18 changed files with 83 additions and 32 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/unittest-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ on: [push]

jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10"]
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ install:
$(PYTHON) setup.py install

sdist: clean ztpserver.spec
$(PYTHON) setup.py sdist
$(PYTHON) setup.py sdist

sdist-dev: clean ztpserver.spec
DEV_VERSION_HASH=$$(git rev-parse --short HEAD) $(PYTHON) setup.py sdist

docker_dev: sdist
@docker build -t ${IMG} .
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Dependencies

Server
======
* Python 3.7 or later (https://www.python.org/downloads)
* Python 3.6 or later (https://www.python.org/downloads)
* routes 2.5 or later (https://pypi.python.org/pypi/Routes)
* webob 1.8 or later (http://webob.org/)
* PyYaml 6.0 or later (http://pyyaml.org/)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.0.0
2.0.1
25 changes: 16 additions & 9 deletions actions/install_image
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,25 @@

# pylint: disable=C0209

from pkg_resources import parse_version
import re

from six import raise_from

BOOT_CONFIG = "/mnt/flash/boot-config"


def remove_eos_release_kind(version):
if version[-1] in ("M", "F"):
return version[:-1]
return version
EOS_VERSION_REGEXP = r"^(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?[a-zA-Z]+$"


def parse_eos_version(version):
match = re.match(EOS_VERSION_REGEXP, version)
if match is None:
raise RuntimeError("invalid version {}".format(version))

major, minor, patch, build = match.groups()
version_tuple = (major, minor, patch, build or 0)

return tuple(map(int, version_tuple))


def main(attributes):
Expand Down Expand Up @@ -98,10 +107,8 @@ def main(attributes):
return

# Don't downgrade images if flag is set
if downgrade is not True:
if parse_version(remove_eos_release_kind(version)) < parse_version(
remove_eos_release_kind(current_version)
):
if not downgrade:
if parse_eos_version(version) < parse_eos_version(current_version):
node.log_msg("install_image: nothing to do: downgrade disabled")
return

Expand Down
13 changes: 9 additions & 4 deletions client/bootstrap
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@
# Written by:
# EOS+, Arista Networks

# pylint: disable=W0703,C0209,C0415,W4901
# pylint: disable=W0703,C0209,C0415,W4901,C0413

import os
import sys

if os.path.exists("/usr/bin/arista-python") and os.path.realpath(
sys.executable
) != os.path.realpath("/usr/bin/arista-python"):
os.execl("/usr/bin/python3", "python3", os.path.abspath(__file__))

import argparse
import crypt
Expand All @@ -41,13 +49,10 @@ import grp
import io
import json
import logging
import os
import os.path
import pwd
import re
import shutil
import subprocess
import sys
import time
import traceback
from collections import namedtuple
Expand Down
4 changes: 2 additions & 2 deletions docs/ReleaseNotes2.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ New Modules
Enhancements
^^^^^^^^^^^^

* Server py3 support (`382 <https://github.com/arista-eosplus/ztpserver/pull/382>`_) [`dlobato <https://github.com/arista-eosplus/ztpserver/pull/382>`_]
* Boostrap + actions py2/py3 support (`388 <https://github.com/arista-eosplus/ztpserver/pull/388>`_) [`dlobato <https://github.com/arista-eosplus/ztpserver/pull/388>`_]
* Server py3 support (`382 <https://github.com/arista-eosplus/ztpserver/pull/382>`_) [`dlobato <https://github.com/dlobato>`_]
* Boostrap + actions py2/py3 support (`388 <https://github.com/arista-eosplus/ztpserver/pull/388>`_) [`dlobato <https://github.com/dlobato>`_]
* CI github actions pipeline

Fixed
Expand Down
20 changes: 20 additions & 0 deletions docs/ReleaseNotes2.0.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Release 2.0.1
-------------

New Modules
^^^^^^^^^^^

Enhancements
^^^^^^^^^^^^

* Force executing bootstrap script with python3 if available (`398 <https://github.com/arista-eosplus/ztpserver/pull/398>`_)[`dlobato <https://github.com/dlobato>`_]

Fixed
^^^^^

* Fixed binary file hashing while extrating metadata (`396 <https://github.com/arista-eosplus/ztpserver/pull/396>`_)[`dlobato <https://github.com/dlobato>`_]
* Fixed install_image action (`397 <https://github.com/arista-eosplus/ztpserver/pull/397>`_)[`dlobato <https://github.com/dlobato>`_]


Known Caveats
^^^^^^^^^^^^^
7 changes: 6 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode']
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinxcontrib.httpdomain', 'sphinxcontrib.napoleon']
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.viewcode",
"sphinxcontrib.httpdomain",
"sphinx.ext.napoleon",
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Expand Down
4 changes: 2 additions & 2 deletions docs/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Requirements

**Server:**

* Python 3.7 or later (https://www.python.org/download/releases)
* Python 3.6 or later (https://www.python.org/download/releases)
* routes 2.5 or later (https://pypi.python.org/pypi/Routes)
* webob 1.8 or later (http://webob.org/)
* PyYaml 6.0 or later (http://pyyaml.org/)
Expand All @@ -30,7 +30,7 @@ Installation Options
.. _packer_install:

Turn-key VM Creation (deprecated)
~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The turn-key VM option leverages `Packer <http://www.packer.io/>`_ to auto generate a VM on your local system. Packer.io automates the creation of the ZTPServer VM. All of the required packages and dependencies are installed and configured. The current Packer configuration allows you to choose between VirtualBox or VMWare as your hypervisor and each can support Fedora 20 or Ubuntu Server 12.04.

Expand Down
1 change: 0 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
-r ../requirements.txt
sphinx
sphinx_rtd_theme
sphinxcontrib-napoleon
sphinxcontrib-httpdomain
1 change: 1 addition & 0 deletions docs/support.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ The authoritative state for any known issue can be found in `GitHub issues <http
:maxdepth: 2
:titlesonly:

ReleaseNotes2.0.1
ReleaseNotes2.0.0
ReleaseNotes1.6.0
ReleaseNotes1.5.0
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ def get_long_description():
x.strip() for x in install_requirements if x.strip() and "dev only" not in x
]
version = open("VERSION").read().split()[0].strip()
if os.environ.get("DEV_VERSION_HASH"):
version = f"{version}+{os.environ.get('DEV_VERSION_HASH')}"

data_files = []
# configuration folders are not cleared on upgrade/downgrade
Expand Down
8 changes: 6 additions & 2 deletions test/server/test_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#
import unittest
from test.server.server_test_lib import enable_logging, random_string
from unittest.mock import patch
from unittest.mock import mock_open, patch

from ztpserver.repository import (
FileObject,
Expand Down Expand Up @@ -63,7 +63,6 @@ def test_read_failure(self, m_load):
@classmethod
@patch("ztpserver.serializers.dump")
def test_write_success(cls, _):
obj = FileObjectError(random_string())
obj = FileObject(random_string())
obj.write(random_string())

Expand All @@ -73,6 +72,11 @@ def test_write_failure(self, m_dump):
obj = FileObject(random_string())
self.assertRaises(FileObjectError, obj.write, random_string())

@patch("builtins.open", new_callable=mock_open, read_data=b"some data")
def test_hash_success(self, _):
obj = FileObject(random_string())
self.assertEqual("baf34551fecb48acc3da868eb85e1b6dac9de356", obj.hash())


class RepositoryUnitTests(unittest.TestCase):
@classmethod
Expand Down
4 changes: 2 additions & 2 deletions ztpserver/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def enable_handler_console(level=None):

def python_supported():
"""Returns True if the current version of the python runtime is valid"""
return sys.version_info >= (3, 7)
return sys.version_info >= (3, 6)


logging_started = False # pylint: disable=C0103
Expand Down Expand Up @@ -131,7 +131,7 @@ def start_wsgiapp(config_file=None, debug=False):
log.info("Using repository %s", config.runtime.default.data_root)

if not python_supported():
raise SystemExit("ERROR: ZTPServer requires Python >= 3.8")
raise SystemExit("ERROR: ZTPServer requires Python >= 3.6")

return controller.Router()

Expand Down
2 changes: 1 addition & 1 deletion ztpserver/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ def metadata(self, request, **kwargs):
self.BODY["size"] = file_resource.size()
self.BODY["sha1"] = file_resource.hash()
resp = {"body": self.BODY, "content_type": CONTENT_TYPE_JSON}
except OSError as exc:
except Exception as exc:
log.error("Failed to collect meta information for %s: %s", file_path, exc)
resp = self.http_internal_server_error()
return resp
Expand Down
9 changes: 7 additions & 2 deletions ztpserver/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class FileObjectNotFound(RepositoryError):


class FileObject:
BUF_SIZE = 65536
"""The :py:class:`FileObject` represents a single file entity in the
repository. The instance provides convienent methods to read and write
contents to the file using a specified serialization
Expand Down Expand Up @@ -171,8 +172,12 @@ def hash(self):
"""

sha1 = hashlib.sha1()
with open(self.name, encoding="utf8") as fd:
sha1.update(fd.read().encode("utf8")) # pylint: disable=E1101
with open(self.name, mode="rb") as fd:
while True:
data = fd.read(self.BUF_SIZE)
if not data:
break
sha1.update(data)
return sha1.hexdigest()


Expand Down
2 changes: 1 addition & 1 deletion ztpserver/wsgiapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def __call__(self, request):
result = method(request, **request.urlvars)
except Exception as exc:
log.error("Unrecoverable error detected: %s", exc)
raise webob.exc.HTTPInternalServerError()
raise webob.exc.HTTPInternalServerError() from exc

if result is None:
result = webob.exc.HTTPNoContent()
Expand Down

0 comments on commit f079163

Please sign in to comment.