Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cgroupspy to _vendor folder #22206

Merged
merged 2 commits into from
Mar 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ The text of each license is also included at licenses/LICENSE-[project].txt.

(BSD 3 License) d3 v5.16.0 (https://d3js.org)
(BSD 3 License) d3-shape v2.1.0 (https://github.com/d3/d3-shape)
(BSD 3 License) cgroupspy 0.2.1 (https://github.com/cloudsigma/cgroupspy)

========================================================================
See licenses/LICENSES-ui.txt for packages used in `/airflow/www`
37 changes: 37 additions & 0 deletions airflow/_vendor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Vendor package

## What vendored packages are for

The `airflow._vendor` package is foreseen for vendoring in packages, that we have to modify ourselves
because authors of the packages do not have time to modify them themselves. This is often temporary
and once the packages implement fixes that we need, and then we remove the packages from
the `_vendor` package.

All Vendored libraries must follow these rules:

1. Vendored libraries must be pure Python--no compiling (so that we do not have to release multi-platform airflow packages on PyPI).
2. Source code for the libary is included in this directory.
3. License must be included in this repo and in the [LICENSE](../../LICENSE) file and in the
[licenses](../../licenses) folder.
4. Requirements of the library become requirements of airflow core.
5. Version of the library should be included in the [vendor.md](vendor.md) file.
6. No modifications to the library may be made in the initial commit.
7. Apply the fixes necessary to use the vendored library as separate commits - each package separately,
so that they can be cherry-picked later if we upgrade the vendored package. Changes to airflow code to
use the vendored packages should be applied as separate commits/PRs.
8. The `_vendor` packages should be excluded from any refactorings, static checks and automated fixes.

## Adding and upgrading a vendored package

Way to vendor a library or update a version:

1. Update ``vendor.txt`` with the library, version, and SHA256 (`pypi` provides hashes as of recently)
2. Remove all old files and directories of the old version.
3. Replace them with new files (only replace relevant python packages:move LICENSE )
* move licence files to [licenses](../../licenses) folder
* remove README and any other supporting files (they can be found in PyPI)
* make sure to add requirements from setup.py to airflow's setup.py with appropriate comment stating
why the requirements are added and when they should be removed
4. If you replace previous version, re-apply historical fixes from the "package" folder by
cherry-picking them.

27 changes: 27 additions & 0 deletions airflow/_vendor/cgroupspy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Copyright (c) 2014, CloudSigma AG
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the CloudSigma AG nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL CloudSigma AG BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
__version__ = "0.2.1"
155 changes: 155 additions & 0 deletions airflow/_vendor/cgroupspy/contenttypes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
"""
Copyright (c) 2014, CloudSigma AG
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the CloudSigma AG nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL CLOUDSIGMA AG BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""


class BaseContentType(object):

def __str__(self):
raise NotImplementedError("Please implement this method in subclass")

def __repr__(self):
return "<{self.__class__.__name__}: {self}>".format(self=self)

@classmethod
def from_string(cls, value):
raise NotImplementedError("This method should return an instance of the content type")


class DeviceAccess(BaseContentType):
TYPE_ALL = "all"
TYPE_CHAR = "c"
TYPE_BLOCK = "b"

ACCESS_UNSPEC = 0
ACCESS_READ = 1
ACCESS_WRITE = 2
ACCESS_MKNOD = 4

def __init__(self, dev_type=None, major=None, minor=None, access=None):
self.dev_type = dev_type or self.TYPE_ALL

# the default behaviour of device access cgroups if unspecified is as follows
if major is not None:
self.major = int(major)
else:
self.major = "*"

if minor is not None:
self.minor = int(minor)
else:
self.minor = "*"

if isinstance(access, str):
value = 0
if 'r' in access:
value |= self.ACCESS_READ
if 'w' in access:
value |= self.ACCESS_WRITE
if 'm' in access:
value |= self.ACCESS_MKNOD
self.access = value
else:
self.access = access or (self.ACCESS_READ | self.ACCESS_WRITE | self.ACCESS_MKNOD)

def _check_access_bit(self, offset):
mask = 1 << offset
return self.access & mask

@property
def can_read(self):
return self._check_access_bit(0) == self.ACCESS_READ

@property
def can_write(self):
return self._check_access_bit(1) == self.ACCESS_WRITE

@property
def can_mknod(self):
return self._check_access_bit(2) == self.ACCESS_MKNOD

@property
def access_string(self):
accstr = ""
if self.can_read:
accstr += "r"
if self.can_write:
accstr += "w"
if self.can_mknod:
accstr += "m"
return accstr

def __str__(self):
return "{self.dev_type} {self.major}:{self.minor} {self.access_string}".format(self=self)

def __eq__(self, other):
return self.dev_type == other.dev_type and self.major == other.major \
and self.minor == other.minor and self.access_string == other.access_string

@classmethod
def from_string(cls, value):
dev_type, major_minor, access_string = value.split()
major, minor = major_minor.split(":")
major = int(major) if major != "*" else None
minor = int(minor) if minor != "*" else None

access_mode = 0
for idx, char in enumerate("rwm"):
if char in access_string:
access_mode |= (1 << idx)
return cls(dev_type, major, minor, access_mode)


class DeviceThrottle(BaseContentType):

def __init__(self, limit, major=None, minor=None, ):
self.limit = limit

if major is not None and major != '*':
self.major = int(major)
else:
self.major = '*'

if minor is not None and minor != '*':
self.minor = int(minor)
else:
self.minor = '*'

def __eq__(self, other):
return self.limit == other.limit and self.major == other.major and self.minor == other.minor

def __str__(self):
return "{self.major}:{self.minor} {self.limit}".format(self=self)

@classmethod
def from_string(cls, value):
try:
major_minor, limit = value.split()
major, minor = major_minor.split(":")
return cls(int(limit), major, minor)
except Exception:
raise RuntimeError("Value {} cannot be converted to a string that matches the pattern: "
"[device major]:[device minor] [throttle limit in bytes]".format(value))
Loading