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

Allow creation from dict #795

Merged
merged 19 commits into from
Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 2 additions & 1 deletion kubernetes/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@

from __future__ import absolute_import

from .create_from_yaml import FailToCreateError, create_from_yaml
from .create_from_yaml import (FailToCreateError, create_from_yaml,
create_from_map)
71 changes: 40 additions & 31 deletions kubernetes/utils/create_from_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import io
import re

from os import path

import yaml
Expand All @@ -30,7 +30,7 @@ def create_from_yaml(
Perform an action from a yaml file. Pass True for verbose to
print confirmation information.
Input:
yaml_file: string. Contains the path to yaml file.
yaml_file: string. Contains yaml string or a path to yaml file.
Copy link
Contributor

@juliantaylor juliantaylor Mar 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be a bit odd to expect a yaml string as input.
Wrapping preexisting strings into file-like objects is normally done by the caller the reasoning being if you have already have stream you have to read it into memory just for the function to convert it back to a memory stream.
Wrapping a pre-existing memory object into a stream on the otherhand is cheap as it just boils down to a memory view.

The usual interface is file path or file-like object. a file-like is also still acceptable for the argument name yaml_file, while that name does not really fit for a string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason we want to support string input is that kubectl create -f - takes a stdin input. I know it's kinda weird since bash does not really have dicts, but the functionality is there...

https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#create

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that kind of my point stdin is not a string, stdin is a file-like object
so to use this function like kubectl create -f - you call create_from_yaml(sys.stdin)
the mapping of a potential - commandline argument to stdin should be done by the caller

oz123 marked this conversation as resolved.
Show resolved Hide resolved
k8s_client: an ApiClient object, initialized with the client args.
verbose: If True, print confirmation from the create action.
Default is False.
Expand All @@ -54,35 +54,44 @@ def create_from_yaml(
processing of the request.
Valid values are: - All: all dry run stages will be processed
"""
if path.exists(yaml_file):
oz123 marked this conversation as resolved.
Show resolved Hide resolved
with open(path.abspath(yaml_file)) as f:
oz123 marked this conversation as resolved.
Show resolved Hide resolved
yaml_file = io.StringIO(f.read())

yml_document_all = yaml.safe_load_all(yaml_file)
# Load all documents from a single YAML file
for yml_document in yml_document_all:
create_from_map(k8s_client, yml_document, verbose,
**kwargs)


def create_from_map(k8s_client, yml_document, verbose=False, **kwargs):
oz123 marked this conversation as resolved.
Show resolved Hide resolved
# If it is a list type, will need to iterate its items
api_exceptions = []

if "List" in yml_document["kind"]:
# Could be "List" or "Pod/Service/...List"
# This is a list type. iterate within its items
kind = yml_document["kind"].replace("List", "")
for yml_object in yml_document["items"]:
# Mitigate cases when server returns a xxxList object
# See kubernetes-client/python#586
if kind is not "":
yml_object["apiVersion"] = yml_document["apiVersion"]
yml_object["kind"] = kind
try:
create_from_yaml_single_item(
k8s_client, yml_object, verbose, **kwargs)
except client.rest.ApiException as api_exception:
api_exceptions.append(api_exception)
else:
# This is a single object. Call the single item method
try:
create_from_yaml_single_item(
k8s_client, yml_document, verbose, **kwargs)
except client.rest.ApiException as api_exception:
api_exceptions.append(api_exception)

with open(path.abspath(yaml_file)) as f:
yml_document_all = yaml.safe_load_all(f)
api_exceptions = []
# Load all documents from a single YAML file
for yml_document in yml_document_all:
# If it is a list type, will need to iterate its items
if "List" in yml_document["kind"]:
# Could be "List" or "Pod/Service/...List"
# This is a list type. iterate within its items
kind = yml_document["kind"].replace("List", "")
for yml_object in yml_document["items"]:
# Mitigate cases when server returns a xxxList object
# See kubernetes-client/python#586
if kind is not "":
yml_object["apiVersion"] = yml_document["apiVersion"]
yml_object["kind"] = kind
try:
create_from_yaml_single_item(
k8s_client, yml_object, verbose, **kwargs)
except client.rest.ApiException as api_exception:
api_exceptions.append(api_exception)
else:
# This is a single object. Call the single item method
try:
create_from_yaml_single_item(
k8s_client, yml_document, verbose, **kwargs)
except client.rest.ApiException as api_exception:
api_exceptions.append(api_exception)
# In case we have exceptions waiting for us, raise them
if api_exceptions:
raise FailToCreateError(api_exceptions)
Expand Down