Merge pull request #2172 from yliaog/automated-release-of-29.0.0b1-upstream-release-29.0-1703785760
Automated release of 29.0.0b1 upstream release 29.0 1703785760
This commit is contained in:
commit
e5abf1428a
2
.github/workflows/e2e-master.yaml
vendored
2
.github/workflows/e2e-master.yaml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
# as we sync with Kubernetes upstream
|
||||
config: .github/workflows/kind-configs/cluster-1.25.yaml
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
2
.github/workflows/e2e-release-11.0.yaml
vendored
2
.github/workflows/e2e-release-11.0.yaml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
# as we sync with Kubernetes upstream
|
||||
config: .github/workflows/kind-configs/cluster-1.15.yaml
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
2
.github/workflows/e2e-release-12.0.yaml
vendored
2
.github/workflows/e2e-release-12.0.yaml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
# as we sync with Kubernetes upstream
|
||||
config: .github/workflows/kind-configs/cluster-1.16.yaml
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
2
.github/workflows/e2e-release-17.0.yaml
vendored
2
.github/workflows/e2e-release-17.0.yaml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
# as we sync with Kubernetes upstream
|
||||
config: .github/workflows/kind-configs/cluster-1.17.yaml
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
2
.github/workflows/e2e-release-18.0.yaml
vendored
2
.github/workflows/e2e-release-18.0.yaml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
# as we sync with Kubernetes upstream
|
||||
config: .github/workflows/kind-configs/cluster-1.18.yaml
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
2
.github/workflows/e2e-release-26.0.yaml
vendored
2
.github/workflows/e2e-release-26.0.yaml
vendored
@ -30,7 +30,7 @@ jobs:
|
||||
# as we sync with Kubernetes upstream
|
||||
config: .github/workflows/kind-configs/cluster-1.26.yaml
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
2
.github/workflows/test.yaml
vendored
2
.github/workflows/test.yaml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
with:
|
||||
submodules: true
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
|
||||
@ -1,3 +1,11 @@
|
||||
# v29.0.0b1
|
||||
|
||||
Kubernetes API Version: v1.29.0
|
||||
|
||||
### Bug or Regression
|
||||
- Fix UTF-8 failures in Watch (#2100, @davidopic)
|
||||
- Fix upper version boundary of urllib3, since other dependencies don't support urllib3 in version 2 (#2105, @jsaalfeld)
|
||||
|
||||
# v29.0.0a1
|
||||
|
||||
Kubernetes API Version: v1.29.0
|
||||
|
||||
@ -4,7 +4,7 @@ No description provided (generated by Openapi Generator https://github.com/opena
|
||||
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: release-1.29
|
||||
- Package version: 29.0.0a1
|
||||
- Package version: 29.0.0b1
|
||||
- Build package: org.openapitools.codegen.languages.PythonClientCodegen
|
||||
|
||||
## Requirements.
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
__project__ = 'kubernetes'
|
||||
# The version is auto-updated. Please do not edit.
|
||||
__version__ = "29.0.0a1"
|
||||
__version__ = "29.0.0b1"
|
||||
|
||||
from . import client
|
||||
from . import config
|
||||
|
||||
@ -52,20 +52,33 @@ def _find_return_type(func):
|
||||
|
||||
|
||||
def iter_resp_lines(resp):
|
||||
prev = ""
|
||||
for seg in resp.stream(amt=None, decode_content=False):
|
||||
if isinstance(seg, bytes):
|
||||
seg = seg.decode('utf8')
|
||||
seg = prev + seg
|
||||
lines = seg.split("\n")
|
||||
if not seg.endswith("\n"):
|
||||
prev = lines[-1]
|
||||
lines = lines[:-1]
|
||||
buffer = bytearray()
|
||||
for segment in resp.stream(amt=None, decode_content=False):
|
||||
|
||||
# Append the segment (chunk) to the buffer
|
||||
#
|
||||
# Performance note: depending on contents of buffer and the type+value of segment,
|
||||
# encoding segment into the buffer could be a wasteful step. The approach used here
|
||||
# simplifies the logic farther down, but in the future it may be reasonable to
|
||||
# sacrifice readability for performance.
|
||||
if isinstance(segment, bytes):
|
||||
buffer.extend(segment)
|
||||
elif isinstance(segment, str):
|
||||
buffer.extend(segment.encode("utf-8"))
|
||||
else:
|
||||
prev = ""
|
||||
for line in lines:
|
||||
raise TypeError(
|
||||
f"Received invalid segment type, {type(segment)}, from stream. Accepts only 'str' or 'bytes'.")
|
||||
|
||||
# Split by newline (safe for utf-8 because multi-byte sequences cannot contain the newline byte)
|
||||
next_newline = buffer.find(b'\n')
|
||||
while next_newline != -1:
|
||||
# Convert bytes to a valid utf-8 string, replacing any invalid utf-8 with the '<27>' character
|
||||
line = buffer[:next_newline].decode(
|
||||
"utf-8", errors="replace")
|
||||
buffer = buffer[next_newline+1:]
|
||||
if line:
|
||||
yield line
|
||||
next_newline = buffer.find(b'\n')
|
||||
|
||||
|
||||
class Watch(object):
|
||||
|
||||
@ -61,6 +61,9 @@ class WatchTests(unittest.TestCase):
|
||||
if count == 4:
|
||||
w.stop()
|
||||
|
||||
# make sure that all three records were consumed by the stream
|
||||
self.assertEqual(4, count)
|
||||
|
||||
fake_api.get_namespaces.assert_called_once_with(
|
||||
_preload_content=False, watch=True)
|
||||
fake_resp.stream.assert_called_once_with(
|
||||
@ -68,6 +71,123 @@ class WatchTests(unittest.TestCase):
|
||||
fake_resp.close.assert_called_once()
|
||||
fake_resp.release_conn.assert_called_once()
|
||||
|
||||
def test_watch_with_interspersed_newlines(self):
|
||||
fake_resp = Mock()
|
||||
fake_resp.close = Mock()
|
||||
fake_resp.release_conn = Mock()
|
||||
fake_resp.stream = Mock(
|
||||
return_value=[
|
||||
'\n',
|
||||
'{"type": "ADDED", "object": {"metadata":',
|
||||
'{"name": "test1","resourceVersion": "1"}}}\n{"type": "ADDED", ',
|
||||
'"object": {"metadata": {"name": "test2", "resourceVersion": "2"}}}\n',
|
||||
'\n',
|
||||
'',
|
||||
'{"type": "ADDED", "object": {"metadata": {"name": "test3", "resourceVersion": "3"}}}\n',
|
||||
'\n\n\n',
|
||||
'\n',
|
||||
])
|
||||
|
||||
fake_api = Mock()
|
||||
fake_api.get_namespaces = Mock(return_value=fake_resp)
|
||||
fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList'
|
||||
|
||||
w = Watch()
|
||||
count = 0
|
||||
|
||||
# Consume all test events from the mock service, stopping when no more data is available.
|
||||
# Note that "timeout_seconds" below is not a timeout; rather, it disables retries and is
|
||||
# the only way to do so. Without that, the stream will re-read the test data forever.
|
||||
for e in w.stream(fake_api.get_namespaces, timeout_seconds=1):
|
||||
count += 1
|
||||
self.assertEqual("test%d" % count, e['object'].metadata.name)
|
||||
self.assertEqual(3, count)
|
||||
|
||||
def test_watch_with_multibyte_utf8(self):
|
||||
fake_resp = Mock()
|
||||
fake_resp.close = Mock()
|
||||
fake_resp.release_conn = Mock()
|
||||
fake_resp.stream = Mock(
|
||||
return_value=[
|
||||
# two-byte utf-8 character
|
||||
'{"type":"MODIFIED","object":{"data":{"utf-8":"© 1"},"metadata":{"name":"test1","resourceVersion":"1"}}}\n',
|
||||
# same copyright character expressed as bytes
|
||||
b'{"type":"MODIFIED","object":{"data":{"utf-8":"\xC2\xA9 2"},"metadata":{"name":"test2","resourceVersion":"2"}}}\n'
|
||||
# same copyright character with bytes split across two stream chunks
|
||||
b'{"type":"MODIFIED","object":{"data":{"utf-8":"\xC2',
|
||||
b'\xA9 3"},"metadata":{"n',
|
||||
# more chunks of the same event, sent as a mix of bytes and strings
|
||||
'ame":"test3","resourceVersion":"3"',
|
||||
'}}}',
|
||||
b'\n'
|
||||
])
|
||||
|
||||
fake_api = Mock()
|
||||
fake_api.get_configmaps = Mock(return_value=fake_resp)
|
||||
fake_api.get_configmaps.__doc__ = ':return: V1ConfigMapList'
|
||||
|
||||
w = Watch()
|
||||
count = 0
|
||||
|
||||
# Consume all test events from the mock service, stopping when no more data is available.
|
||||
# Note that "timeout_seconds" below is not a timeout; rather, it disables retries and is
|
||||
# the only way to do so. Without that, the stream will re-read the test data forever.
|
||||
for event in w.stream(fake_api.get_configmaps, timeout_seconds=1):
|
||||
count += 1
|
||||
self.assertEqual("MODIFIED", event['type'])
|
||||
self.assertEqual("test%d" % count, event['object'].metadata.name)
|
||||
self.assertEqual("© %d" % count, event['object'].data["utf-8"])
|
||||
self.assertEqual(
|
||||
"%d" % count, event['object'].metadata.resource_version)
|
||||
self.assertEqual("%d" % count, w.resource_version)
|
||||
self.assertEqual(3, count)
|
||||
|
||||
def test_watch_with_invalid_utf8(self):
|
||||
fake_resp = Mock()
|
||||
fake_resp.close = Mock()
|
||||
fake_resp.release_conn = Mock()
|
||||
fake_resp.stream = Mock(
|
||||
# test 1 uses 1 invalid utf-8 byte
|
||||
# test 2 uses a sequence of 2 invalid utf-8 bytes
|
||||
# test 3 uses a sequence of 3 invalid utf-8 bytes
|
||||
return_value=[
|
||||
# utf-8 sequence for 😄 is \xF0\x9F\x98\x84
|
||||
# all other sequences below are invalid
|
||||
# ref: https://www.w3.org/2001/06/utf-8-wrong/UTF-8-test.html
|
||||
b'{"type":"MODIFIED","object":{"data":{"utf-8":"\xF0\x9F\x98\x84 1","invalid":"\x80 1"},"metadata":{"name":"test1"}}}\n',
|
||||
b'{"type":"MODIFIED","object":{"data":{"utf-8":"\xF0\x9F\x98\x84 2","invalid":"\xC0\xAF 2"},"metadata":{"name":"test2"}}}\n',
|
||||
# mix bytes/strings and split byte sequences across chunks
|
||||
b'{"type":"MODIFIED","object":{"data":{"utf-8":"\xF0\x9F\x98',
|
||||
b'\x84 ',
|
||||
b'',
|
||||
b'3","invalid":"\xE0\x80',
|
||||
b'\xAF ',
|
||||
'3"},"metadata":{"n',
|
||||
'ame":"test3"',
|
||||
'}}}',
|
||||
b'\n'
|
||||
])
|
||||
|
||||
fake_api = Mock()
|
||||
fake_api.get_configmaps = Mock(return_value=fake_resp)
|
||||
fake_api.get_configmaps.__doc__ = ':return: V1ConfigMapList'
|
||||
|
||||
w = Watch()
|
||||
count = 0
|
||||
|
||||
# Consume all test events from the mock service, stopping when no more data is available.
|
||||
# Note that "timeout_seconds" below is not a timeout; rather, it disables retries and is
|
||||
# the only way to do so. Without that, the stream will re-read the test data forever.
|
||||
for event in w.stream(fake_api.get_configmaps, timeout_seconds=1):
|
||||
count += 1
|
||||
self.assertEqual("MODIFIED", event['type'])
|
||||
self.assertEqual("test%d" % count, event['object'].metadata.name)
|
||||
self.assertEqual("😄 %d" % count, event['object'].data["utf-8"])
|
||||
# expect N replacement characters in test N
|
||||
self.assertEqual("<EFBFBD> %d".replace('<EFBFBD>', '<EFBFBD>'*count) %
|
||||
count, event['object'].data["invalid"])
|
||||
self.assertEqual(3, count)
|
||||
|
||||
def test_watch_for_follow(self):
|
||||
fake_resp = Mock()
|
||||
fake_resp.close = Mock()
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
__version__ = "29.0.0a1"
|
||||
__version__ = "29.0.0b1"
|
||||
|
||||
# import apis into sdk package
|
||||
from kubernetes.client.api.well_known_api import WellKnownApi
|
||||
|
||||
@ -78,7 +78,7 @@ class ApiClient(object):
|
||||
self.default_headers[header_name] = header_value
|
||||
self.cookie = cookie
|
||||
# Set default User-Agent.
|
||||
self.user_agent = 'OpenAPI-Generator/29.0.0a1/python'
|
||||
self.user_agent = 'OpenAPI-Generator/29.0.0b1/python'
|
||||
self.client_side_validation = configuration.client_side_validation
|
||||
|
||||
def __enter__(self):
|
||||
|
||||
@ -354,7 +354,7 @@ class Configuration(object):
|
||||
"OS: {env}\n"\
|
||||
"Python Version: {pyversion}\n"\
|
||||
"Version of the API: release-1.29\n"\
|
||||
"SDK Package Version: 29.0.0a1".\
|
||||
"SDK Package Version: 29.0.0b1".\
|
||||
format(env=sys.platform, pyversion=sys.version)
|
||||
|
||||
def get_host_settings(self):
|
||||
|
||||
@ -18,13 +18,13 @@ import sys
|
||||
KUBERNETES_BRANCH = "release-1.29"
|
||||
|
||||
# client version for packaging and releasing.
|
||||
CLIENT_VERSION = "29.0.0a1"
|
||||
CLIENT_VERSION = "29.0.0b1"
|
||||
|
||||
# Name of the release package
|
||||
PACKAGE_NAME = "kubernetes"
|
||||
|
||||
# Stage of development, mainly used in setup.py's classifiers.
|
||||
DEVELOPMENT_STATUS = "3 - Alpha"
|
||||
DEVELOPMENT_STATUS = "4 - Beta"
|
||||
|
||||
|
||||
# If called directly, return the constant value given
|
||||
|
||||
4
setup.py
4
setup.py
@ -16,9 +16,9 @@ from setuptools import setup
|
||||
|
||||
# Do not edit these constants. They will be updated automatically
|
||||
# by scripts/update-client.sh.
|
||||
CLIENT_VERSION = "29.0.0a1"
|
||||
CLIENT_VERSION = "29.0.0b1"
|
||||
PACKAGE_NAME = "kubernetes"
|
||||
DEVELOPMENT_STATUS = "3 - Alpha"
|
||||
DEVELOPMENT_STATUS = "4 - Beta"
|
||||
|
||||
# To install the library, run the following
|
||||
#
|
||||
|
||||
Loading…
Reference in New Issue
Block a user