Skip to content
This repository was archived by the owner on Dec 1, 2018. It is now read-only.
Open
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
5 changes: 5 additions & 0 deletions pykube/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@
ThirdPartyResource,
)
from .query import now, all_ as all, everything # noqa

# temporarily
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
17 changes: 14 additions & 3 deletions pykube/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def from_service_account(cls, path="/var/run/secrets/kubernetes.io/serviceaccoun
return self

@classmethod
def from_file(cls, filename):
def from_file(cls, filename="~/.kube/config", verify=False):
"""
Creates an instance of the KubeConfig class from a kubeconfig file.

Expand All @@ -72,7 +72,17 @@ def from_file(cls, filename):
raise exceptions.PyKubeError("Configuration file {} not found".format(filename))
with open(filename) as f:
doc = yaml.safe_load(f.read())
self = cls(doc)
if "clusters" not in doc or not doc["clusters"]:
raise exceptions.PyKubeError("Do not have cluster.")
for i in range(len(doc["clusters"])):
if "name" not in doc["clusters"][i]:
doc["clusters"][i]["name"] = "default" + str(i)
if not doc["contexts"]:
default_cluster = doc["clusters"][0]["name"]
doc["contexts"] = [{"context": {"cluster": default_cluster}, "name": "default"}]
if "current-context" not in doc or not doc["current-context"]:
doc["current-context"] = doc["contexts"][0]["name"]
self = cls(doc, verify)
self.filename = filename
return self

Expand Down Expand Up @@ -104,12 +114,13 @@ def from_url(cls, url):
self = cls(doc)
return self

def __init__(self, doc):
def __init__(self, doc, verify=False):
"""
Creates an instance of the KubeConfig class.
"""
self.doc = doc
self.current_context = None
self.verify = verify
if "current-context" in doc and doc["current-context"]:
self.set_current_context(doc["current-context"])

Expand Down
6 changes: 4 additions & 2 deletions pykube/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(self, config):
"""
self.config = config
self.url = self.config.cluster["server"]
self.session = self.build_session()
self.session = self.build_session(config.verify)

@property
def url(self):
Expand All @@ -43,7 +43,7 @@ def url(self, value):
warnings.warn("IP address hostnames are not supported with Python < 3.5. Please see https://github.com/kelproject/pykube/issues/29 for more info.", RuntimeWarning)
self._url = pr.geturl()

def build_session(self):
def build_session(self, verify=False):
"""
Creates a new session for the client.
"""
Expand All @@ -61,6 +61,8 @@ def build_session(self):
)
else: # no user present; don't configure anything
pass
if not verify:
s.verify = False
return s

def get_kwargs(self, **kwargs):
Expand Down
31 changes: 31 additions & 0 deletions pykube/objects.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import copy
import json
import os.path as op
from time import sleep

import six

Expand Down Expand Up @@ -95,6 +96,24 @@ def delete(self):
if r.status_code != 404:
self.api.raise_for_status(r)

def scale(self, replicas):
r = self.api.patch(**self.api_kwargs(
headers={"Content-Type": "application/merge-patch+json"},
data='{"spec": {"replicas": %d}}' % replicas,
))
if r.status_code != 404:
self.api.raise_for_status(r)

@property
def status(self, all=False):
r = self.api.get(**self.api_kwargs())
if r.status_code != 404:
self.api.raise_for_status(r)
if all:
return r.json()
else:
return r.json()['status']


class NamespacedAPIObject(APIObject):

Expand Down Expand Up @@ -227,6 +246,18 @@ class ReplicationController(NamespacedAPIObject, ReplicatedMixin, ScalableMixin)
endpoint = "replicationcontrollers"
kind = "ReplicationController"

def wait_to_death(self):
while (self.status['replicas'] != 0):
sleep(0.1)
r = self.api.delete(**self.api_kwargs())
if r.status_code != 404:
self.api.raise_for_status(r)

def delete(self, block=True):
self.scale(0)
if block:
self.wait_to_death()


class ReplicaSet(NamespacedAPIObject, ReplicatedMixin, ScalableMixin):

Expand Down
5 changes: 4 additions & 1 deletion test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def test_contexts(self):
{"cluster": "thecluster", "user": "admin"},
self.cfg.contexts.get("thename", None))

'''
Now this will not fail without current_context
def test_cluster(self):
"""
Verify cluster works as expected.
Expand Down Expand Up @@ -101,7 +103,8 @@ def test_user(self):

self.cfg.set_current_context("thename")
self.assertEqual("data", self.cfg.user)

'''

def test_default_user(self):
"""
User can sometimes be specified as 'default' with no corresponding definition
Expand Down