How to use raw YAML file inside a curl to create Pod

10/15/2018

I am trying to create a Pod in Kubernetes using curl.

This is the YAML:

cat > nginx-pod.yaml <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: nginx1
spec:
  containers:
  - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80
EOF

I have token with permissions to do it and I wrote the following curl command:

curl -k -v -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json;charset=utf-8' https://127.0.0.1:6443/api/v1/namespaces/default/pods --data '{"name":"","namespace":"default","content":"apiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx1\nspec:\n  containers:\n  - name: nginx\n    image: nginx:1.7.9\n    ports:\n    - containerPort: 80\n","validate":true}'

Which should be equivalent to the nginx-pod.yaml file.
The YAML is ok because when I runkubectl create -f nginx.pod.yaml it creates it.
But when I tried to run it with curl I received:

< Content-Length: 617
<
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {

  },
  "status": "Failure",
  "message": "Pod \"\" is invalid: [metadata.name: Required value: name or generateName is required, spec.containers: Required value]",
  "reason": "Invalid",
  "details": {
    "kind": "Pod",
    "causes": [
      {
        "reason": "FieldValueRequired",
        "message": "Required value: name or generateName is required",
        "field": "metadata.name"
      },
      {
        "reason": "FieldValueRequired",
        "message": "Required value",
        "field": "spec.containers"
      }
    ]
  },
  "code": 422
* Connection #0 to host 127.0.0.1 left intact

I tried to change the Content-Type to Content-type: text/x-yaml but it didn't help.

Any idea what can be the reason?

One of the errors is regarding the "metadata.name" field.

-- E235
curl
kubernetes
yaml

2 Answers

10/15/2018

The payloads don't seem equivalent.

This is the JSON payload you are sending:

{
  "name": "",
  "namespace": "default",
  "content": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx1\nspec:\n  containers:\n  - name: nginx\n    image: nginx:1.7.9\n    ports:\n    - containerPort: 80\n",
  "validate": true
}

Your payload should be something like this. I created this with kubectl convert -f <yaml.file> -o=json, which is what I believe kubectl does before sending the payload.

{
    "kind": "Pod",
    "apiVersion": "v1",
    "metadata": {
        "name": "nginx1",
        "creationTimestamp": null
    },
    "spec": {
        "containers": [
            {
                "name": "nginx",
                "image": "nginx:1.7.9",
                "ports": [
                    {
                        "containerPort": 80,
                        "protocol": "TCP"
                    }
                ],
                "resources": {},
                "terminationMessagePath": "/dev/termination-log",
                "terminationMessagePolicy": "File",
                "imagePullPolicy": "IfNotPresent"
            }
        ],
        "restartPolicy": "Always",
        "terminationGracePeriodSeconds": 30,
        "dnsPolicy": "ClusterFirst",
        "securityContext": {},
        "schedulerName": "default-scheduler"
    },
    "status": {}
}

Tried this and it works fine for me:

curl -k -v -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json;charset=utf-8' https://127.0.0.1:6443/api/v1/namespaces/default/pods -d@payload.json
-- Rico
Source: StackOverflow

10/15/2018

make sure you set content type to application/yaml, and use --binary-data with yaml… --data drops newlines

-- Jordan Liggitt
Source: StackOverflow