OpenShift REST API for scaling, invalid character 's' looking for beginning of value

11/13/2017

I'm trying to scale out my deployments using openshift rest api, but I'm encountering the error "invalid character 's' looking for beginning of value". I can successfully get the deployment config details but it's the patch request which is troubling me. From the documents I have tried Content-Type as below 3 but nothing works:

  • application/json-patch+json
  • application/merge-patch+json
  • application/strategic-merge-patch+json

Here's my code:

data = {'spec':{'replicas':2}}
headers = {"Authorization": token, "Content-Type": "application/json-patch+json"}
def updateReplicas():
   url = root + "namespaces" + namespace + "deploymentconfigs" + dc + "scale"  
   resp = requests.patch(url, headers=headers, data=data, verify=False)
   print(resp.content)

Thank you.

-- Ankit Sahu
kubernetes
openshift
python
rest

2 Answers

4/11/2019

I had the same use case and the hint of @GrahamDumpleton to run oc with --loglevel 9 was very helpful. This is what oc scale does:

  1. It makes a get request to the resource, receiving some JSON object
  2. Then it makes a put request to the resource, with a modified JSON object (the number of replicas changed) as payload

If you're doing this you don't have to worry about setting the apiVersion, you just reuse what you get in the first place.

Here is a small python script, that follows this approach:

"""
Login into your project first `oc login` and `oc project <your-project>` before running this script.

Usage:
    pip install requests
    python scale_pods.py --deployment-name <your-deployment> --nof-replicas <number>

"""
import argparse
import requests
from subprocess import check_output
import warnings
warnings.filterwarnings("ignore")  # ignore insecure request warnings


def byte_to_str(bs):
    return bs.decode("utf-8").strip()


def get_endpoint():
    byte_str = check_output("echo $(oc config current-context | cut -d/ -f2 | tr - .)", shell=True)
    return byte_to_str(byte_str)


def get_namespace():
    byte_str = check_output("echo $(oc config current-context | cut -d/ -f1)", shell=True)
    return byte_to_str(byte_str)


def get_token():
    byte_str = check_output("echo $(oc whoami -t)", shell=True)
    return byte_to_str(byte_str)


def scale_pods(deployment_name, nof_replicas):
    url = "https://{endpoint}/apis/apps.openshift.io/v1/namespaces/{namespace}/deploymentconfigs/{deplyoment_name}/scale".format(
        endpoint=get_endpoint(),
        namespace=get_namespace(),
        deplyoment_name=deployment_name
    )
    headers = {
        "Authorization": "Bearer %s" % get_token()
    }
    get_response = requests.get(url, headers=headers, verify=False)

    data = get_response.json()
    data["spec"]["replicas"] = nof_replicas
    print(data)

    response_put = requests.put(url, headers=headers, json=data, verify=False)
    print(response_put.status_code)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--deployment-name", type=str, required=True, help="deployment name")
    parser.add_argument("--nof-replicas", type=int, required=True, help="nof replicas")
    args = parser.parse_args()
    scale_pods(args.deployment_name, args.nof_replicas)


if __name__ == "__main__":
    main()
-- Phil
Source: StackOverflow

11/13/2017

Ok, I found out the issue. Silly thing first, data should be inside single quotes data = '{'spec':{'replicas':2}}'.

Then, we need few more info in our data, which finally looks like :

data = '{"kind":"Scale","apiVersion":"extensions/v1beta1","metadata":{"name":"deployment_name","namespace":"namespace_name"},"spec":{"replicas":1}}'

Thank you for your time.

-- Ankit Sahu
Source: StackOverflow