Skip to content

Commit

Permalink
make kubeval hermetic
Browse files Browse the repository at this point in the history
  • Loading branch information
Mengqi Yu committed Apr 22, 2021
1 parent 38546ac commit bcdf539
Show file tree
Hide file tree
Showing 8 changed files with 96,005 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ node_modules
.DS_Store
.nyc_output
bin/
__pycache__

# We use sed -i.bak when doing in-line replace, because it works better cross-platform
*.bak
13 changes: 6 additions & 7 deletions examples/kubeval/simple/README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
# Kubeval
# kubeval: simple example

The `kubeval` KRM config function validates Kubernetes resources using kubeval.
Learn more on the [kubeval website].

This example invokes the kubeval function against Kubernetes v1.18.0.
This example invokes the kubeval function against the builtin Kubernetes
v1.19.8 schema.

## Function invocation

Get this example and try it out by running the following commands:

<!-- TODO: no --network. See: https://github.com/GoogleContainerTools/kpt/issues/1621 -->

```sh
kpt pkg get https://github.com/GoogleContainerTools/kpt-functions-catalog.git/examples/kubeval .
kpt fn run kubeval --network
kpt fn run kubeval
```

## Expected Results

This should give the following output:

```sh
[ERROR] Invalid type. Expected: [integer,null], given: string in object 'v1/ReplicationController//bob' in file example-config.yaml in field spec.replicas
[ERROR] Invalid type. Expected: [integer,null], given: string in object 'v1/ReplicationController//bob' in file resources.yaml in field spec.replicas
error: exit status 1
```

In the `example-config.yaml` file, replace the value of `spec.replicas`
In the `resources.yaml` file, replace the value of `spec.replicas`
with an integer to pass validation and rerun the command. This will return
success (no output).

Expand Down
3 changes: 0 additions & 3 deletions examples/kubeval/simple/fn-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,4 @@ metadata:
config.k8s.io/function: |
container:
image: gcr.io/kpt-fn/kubeval:unstable
network: true
config.kubernetes.io/local-config: 'true'
data:
schema_location: https://kubernetesjsonschema.dev/
9 changes: 7 additions & 2 deletions functions/ts/kubeval/build/kubeval.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM node:14.15-alpine3.12 as builder

ARG KUBEVAL_VERSION="0.15.0"
ARG KUBEVAL_VERSION="v0.16.1"
RUN apk add curl && \
curl -sSLf https://github.com/instrumenta/kubeval/releases/download/${KUBEVAL_VERSION}/kubeval-linux-amd64.tar.gz | \
tar xzf - -C /usr/local/bin
Expand All @@ -27,15 +27,20 @@ RUN npm run build && \

FROM node:14.15-alpine3.12

RUN apk add --update --no-cache python3 py3-pip && ln -sf python3 /usr/bin/python
RUN pip install pyyaml jsonref click
COPY forked/github.com/instrumenta/openapi2jsonschema/*.py /openapi2jsonschema/
RUN chmod +x /openapi2jsonschema/command.py && ln -s /openapi2jsonschema/command.py /usr/bin/openapi2jsonschema

# Run as non-root user as a best-practices:
# https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md
USER node

WORKDIR /home/node/app

COPY --from=builder /home/node/app /home/node/app

COPY --from=builder /usr/local/bin /usr/local/bin
COPY openapi.json /home/node/

ENV PATH /usr/local/bin:$PATH

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
from jsonref import JsonRef # type: ignore
import click

from openapi2jsonschema.log import info, debug, error
from openapi2jsonschema.util import (
from log import info, debug, error
from util import (
additional_properties,
replace_int_or_string,
allow_null_optional_fields,
change_dict_values,
append_no_duplicates,
)
from openapi2jsonschema.errors import UnsupportedError
from errors import UnsupportedError


@click.command()
Expand Down Expand Up @@ -48,11 +48,22 @@
is_flag=True,
help="Prohibits properties not in the schema (additionalProperties: false)",
)
@click.option(
"--apiversionkind",
metavar="apiVersion1,kind1;apiVersion2,kind2",
help="the target resources",
)
@click.argument("schema", metavar="SCHEMA_URL")
def default(output, schema, prefix, stand_alone, expanded, kubernetes, strict):
def default(output, schema, prefix, stand_alone, expanded, kubernetes, strict, apiversionkind):
"""
Converts a valid OpenAPI specification into a set of JSON Schema files
"""
apiVersionKindSet = set()
avkList = apiversionkind.strip("'\"").split(";")
for avk in avkList:
elements = avk.split(",")
apiVersionKindSet.add((elements[0], elements[1].lower()))

info("Downloading schema")
if sys.version_info < (3, 0):
response = urllib.urlopen(schema)
Expand Down Expand Up @@ -96,7 +107,7 @@ def default(output, schema, prefix, stand_alone, expanded, kubernetes, strict):
type_def = definitions[type_name]
if "x-kubernetes-group-version-kind" in type_def:
for kube_ext in type_def["x-kubernetes-group-version-kind"]:
if expanded and "apiVersion" in type_def["properties"]:
if expanded and "properties" in type_def and "apiVersion" in type_def["properties"]:
api_version = (
kube_ext["group"] + "/" +
kube_ext["version"]
Expand All @@ -108,7 +119,7 @@ def default(output, schema, prefix, stand_alone, expanded, kubernetes, strict):
"enum",
api_version,
)
if "kind" in type_def["properties"]:
if "properties" in type_def and "kind" in type_def["properties"]:
kind = kube_ext["kind"]
append_no_duplicates(
type_def["properties"]["kind"], "enum", kind
Expand All @@ -131,6 +142,9 @@ def default(output, schema, prefix, stand_alone, expanded, kubernetes, strict):
if kubernetes:
group = title.split(".")[-3].lower()
api_version = title.split(".")[-2].lower()
tup = (group + "/" + api_version if group and group != "core" else api_version, kind)
if tup not in apiVersionKindSet:
continue
specification = components[title]
specification["$schema"] = "http://json-schema.org/schema#"
specification.setdefault("type", "object")
Expand Down Expand Up @@ -183,7 +197,7 @@ def default(output, schema, prefix, stand_alone, expanded, kubernetes, strict):
specification = updated

if stand_alone:
base = "file://%s/%s/" % (os.getcwd(), output)
base = "file://%s/" % (os.path.realpath(output))
specification = JsonRef.replace_refs(
specification, base_uri=base)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest # type: ignore
from click.testing import CliRunner

from openapi2jsonschema.command import default
from command import default

FIXTURE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../fixtures")

Expand Down
Loading

0 comments on commit bcdf539

Please sign in to comment.