diff --git a/codelab/01_kpt-validate/resources/sample-app/config/frontend/deployment.yaml b/codelab/01_kpt-validate/resources/sample-app/config/frontend/deployment.yaml
new file mode 100644
index 00000000000..cf0efdb0855
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/config/frontend/deployment.yaml
@@ -0,0 +1,28 @@
+apiVersion: apps/v1 # for k8s versions before 1.9.0 use apps/v1beta2 and before 1.8.0 use extensions/v1beta1
+kind: Deployment
+metadata:
+ name: frontend
+spec:
+ selector:
+ matchLabels:
+ app: guestbook
+ tier: frontend
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: guestbook
+ tier: frontend
+ spec:
+ containers:
+ - name: php-redis
+ image: "frontend"
+ resources:
+ requests:
+ cpu: 100m
+ memory: 100Mi
+ env:
+ - name: GET_HOSTS_FROM
+ value: env
+ ports:
+ - containerPort: 80
diff --git a/codelab/01_kpt-validate/resources/sample-app/config/frontend/kustomization.yaml b/codelab/01_kpt-validate/resources/sample-app/config/frontend/kustomization.yaml
new file mode 100644
index 00000000000..f4e19e73795
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/config/frontend/kustomization.yaml
@@ -0,0 +1,3 @@
+resources:
+- service.yaml
+- deployment.yaml
diff --git a/codelab/01_kpt-validate/resources/sample-app/config/frontend/service.yaml b/codelab/01_kpt-validate/resources/sample-app/config/frontend/service.yaml
new file mode 100644
index 00000000000..ba3471cbe6b
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/config/frontend/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: frontend
+ labels:
+ app: guestbook
+ tier: frontend
+spec:
+ type: LoadBalancer
+ ports:
+ - port: 80
+ selector:
+ app: guestbook
+ tier: frontend
diff --git a/codelab/01_kpt-validate/resources/sample-app/config/kustomization.yaml b/codelab/01_kpt-validate/resources/sample-app/config/kustomization.yaml
new file mode 100644
index 00000000000..909f989c694
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/config/kustomization.yaml
@@ -0,0 +1,2 @@
+resources:
+- frontend
diff --git a/codelab/01_kpt-validate/resources/sample-app/php-redis/Dockerfile b/codelab/01_kpt-validate/resources/sample-app/php-redis/Dockerfile
new file mode 100644
index 00000000000..46207880d6e
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/php-redis/Dockerfile
@@ -0,0 +1,30 @@
+# Copyright 2016 The Kubernetes Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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.
+
+FROM php:5-apache
+
+RUN apt-get update
+RUN pear channel-discover pear.nrk.io
+RUN pear install nrk/Predis
+
+# If the container's stdio is connected to systemd-journald,
+# /proc/self/fd/{1,2} are Unix sockets and apache will not be able to open()
+# them. Use "cat" to write directly to the already opened fds without opening
+# them again.
+RUN sed -i 's#ErrorLog /proc/self/fd/2#ErrorLog "|$/bin/cat 1>\&2"#' /etc/apache2/apache2.conf
+RUN sed -i 's#CustomLog /proc/self/fd/1 combined#CustomLog "|/bin/cat" combined#' /etc/apache2/apache2.conf
+
+ADD guestbook.php /var/www/html/guestbook.php
+ADD controllers.js /var/www/html/controllers.js
+ADD index.html /var/www/html/index.html
diff --git a/codelab/01_kpt-validate/resources/sample-app/php-redis/Makefile b/codelab/01_kpt-validate/resources/sample-app/php-redis/Makefile
new file mode 100644
index 00000000000..efd2dbd4b1c
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/php-redis/Makefile
@@ -0,0 +1,80 @@
+# Copyright 2017 The Kubernetes Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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.
+
+TAG = v6
+REGISTRY = gcr.io/yuwenma-gke-playground
+ARCH ?= $(shell go env GOARCH)
+ALL_ARCH = amd64 arm arm64 ppc64le
+
+QEMUVERSION=v2.7.0
+
+IMAGE = $(REGISTRY)/gb-frontend
+MULTI_ARCH_IMG = $(IMAGE)-$(ARCH)
+
+# Set default base image dynamically for each arch
+ifeq ($(ARCH),arm)
+ QEMUARCH=arm
+ BASEIMAGE=armhf/php:5.6-apache
+endif
+ifeq ($(ARCH),arm64)
+ QEMUARCH=aarch64
+ BASEIMAGE=arm64v8/php:5-apache
+endif
+ifeq ($(ARCH),ppc64le)
+ QEMUARCH=ppc64le
+ BASEIMAGE=ppc64le/php:5-apache
+endif
+
+TEMP_DIR := $(shell mktemp -d)
+
+all: all-container
+
+sub-container-%:
+ $(MAKE) ARCH=$* container
+
+sub-push-%:
+ $(MAKE) ARCH=$* push
+
+all-container: $(addprefix sub-container-,$(ALL_ARCH))
+
+all-push: $(addprefix sub-push-,$(ALL_ARCH))
+ docker manifest create --amend $(IMAGE):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(IMAGE)\-&:$(TAG)~g")
+ @for arch in $(ALL_ARCH); do docker manifest annotate --arch $${arch} ${IMAGE}:${TAG} ${IMAGE}-$${arch}:${TAG}; done
+ docker manifest push --purge ${IMAGE}:${TAG}
+
+container: .container-$(ARCH)
+.container-$(ARCH):
+ cp ./* $(TEMP_DIR)
+
+ifneq ($(ARCH),amd64)
+ cd $(TEMP_DIR) && sed -i "s|FROM php.*|FROM $(BASEIMAGE)\nCOPY qemu-$(QEMUARCH)-static /usr/bin\n|g" Dockerfile
+ # Register /usr/bin/qemu-ARCH-static as the handler for ARM binaries in the kernel
+ docker run --rm --privileged multiarch/qemu-user-static:register --reset
+ curl -sSL https://github.com/multiarch/qemu-user-static/releases/download/$(QEMUVERSION)/x86_64_qemu-$(QEMUARCH)-static.tar.gz | tar -xz -C $(TEMP_DIR)
+endif
+ docker build -t $(MULTI_ARCH_IMG):$(TAG) $(TEMP_DIR)
+
+ifeq ($(ARCH), amd64)
+ # This is for to maintain the backward compatibility
+ docker tag $(MULTI_ARCH_IMG):$(TAG) $(IMAGE):$(TAG)
+endif
+
+push: .push-$(ARCH)
+.push-$(ARCH): .container-$(ARCH)
+ docker push $(MULTI_ARCH_IMG):$(TAG)
+
+clean: $(addprefix sub-clean-,$(ALL_ARCH))
+ docker rmi -f $(IMAGE):$(TAG) || true
+sub-clean-%:
+ docker rmi -f $(IMAGE)-$*:$(TAG) || true
diff --git a/codelab/01_kpt-validate/resources/sample-app/php-redis/controllers.js b/codelab/01_kpt-validate/resources/sample-app/php-redis/controllers.js
new file mode 100644
index 00000000000..1e4b5504246
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/php-redis/controllers.js
@@ -0,0 +1,29 @@
+var redisApp = angular.module('redis', ['ui.bootstrap']);
+
+/**
+ * Constructor
+ */
+function RedisController() {}
+
+RedisController.prototype.onRedis = function() {
+ this.scope_.messages.push(this.scope_.msg);
+ this.scope_.msg = "";
+ var value = this.scope_.messages.join();
+ this.http_.get("guestbook.php?cmd=set&key=messages&value=" + value)
+ .success(angular.bind(this, function(data) {
+ this.scope_.redisResponse = "Updated.";
+ }));
+};
+
+redisApp.controller('RedisCtrl', function ($scope, $http, $location) {
+ $scope.controller = new RedisController();
+ $scope.controller.scope_ = $scope;
+ $scope.controller.location_ = $location;
+ $scope.controller.http_ = $http;
+
+ $scope.controller.http_.get("guestbook.php?cmd=get&key=messages")
+ .success(function(data) {
+ console.log(data);
+ $scope.messages = data.data.split(",");
+ });
+});
diff --git a/codelab/01_kpt-validate/resources/sample-app/php-redis/guestbook.php b/codelab/01_kpt-validate/resources/sample-app/php-redis/guestbook.php
new file mode 100644
index 00000000000..ee0670ee69f
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/php-redis/guestbook.php
@@ -0,0 +1,41 @@
+ 'tcp',
+ 'host' => $host,
+ 'port' => 6379,
+ ]);
+
+ $client->set($_GET['key'], $_GET['value']);
+ print('{"message": "Updated"}');
+ } else {
+ $host = 'redis-slave';
+ if (getenv('GET_HOSTS_FROM') == 'env') {
+ $host = getenv('REDIS_SLAVE_SERVICE_HOST');
+ }
+ $client = new Predis\Client([
+ 'scheme' => 'tcp',
+ 'host' => $host,
+ 'port' => 6379,
+ ]);
+
+ $value = $client->get($_GET['key']);
+ print('{"data": "' . $value . '"}');
+ }
+} else {
+ phpinfo();
+} ?>
diff --git a/codelab/01_kpt-validate/resources/sample-app/php-redis/index.html b/codelab/01_kpt-validate/resources/sample-app/php-redis/index.html
new file mode 100644
index 00000000000..b5f25f77b5b
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/php-redis/index.html
@@ -0,0 +1,25 @@
+
+
+ Hello World
+
+
+
+
+
+
+
+
+
diff --git a/codelab/01_kpt-validate/resources/sample-app/skaffold.yaml b/codelab/01_kpt-validate/resources/sample-app/skaffold.yaml
new file mode 100644
index 00000000000..9a9434a875c
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/sample-app/skaffold.yaml
@@ -0,0 +1,11 @@
+apiVersion: skaffold/v2beta8
+kind: Config
+metadata:
+ name: kpt-cl
+build:
+ artifacts:
+ - image: "frontend"
+ context: php-redis
+deploy:
+ kpt:
+ dir: config
diff --git a/codelab/01_kpt-validate/resources/validation-kubeval/fn-kubeval.yaml b/codelab/01_kpt-validate/resources/validation-kubeval/fn-kubeval.yaml
new file mode 100644
index 00000000000..24d354ef89a
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/validation-kubeval/fn-kubeval.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: kubeval
+ annotations:
+ config.kubernetes.io/function: |
+ container:
+ image: gcr.io/kpt-functions/kubeval
+ network: true
diff --git a/codelab/01_kpt-validate/resources/validation-pipeline/fn-pipeline.yaml b/codelab/01_kpt-validate/resources/validation-pipeline/fn-pipeline.yaml
new file mode 100644
index 00000000000..0a7581f5dbd
--- /dev/null
+++ b/codelab/01_kpt-validate/resources/validation-pipeline/fn-pipeline.yaml
@@ -0,0 +1,21 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ # Validates the yaml schema.
+ name: YamlValidate
+ annotations:
+ config.kubernetes.io/function: |
+ container:
+ image: gcr.io/kpt-functions/kubeval
+ network: true
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ # Validates that all containers have cpu and memory reservations set.
+ name: CPUAndMemory
+ annotations:
+ config.kubernetes.io/function: |
+ container:
+ image: gcr.io/kustomize-functions/example-validator-kubeval:v0.1.0
+ network: true
diff --git a/codelab/02_kpt-deploy/resources/sample-app/config/frontend/deployment.yaml b/codelab/02_kpt-deploy/resources/sample-app/config/frontend/deployment.yaml
new file mode 100644
index 00000000000..cf0efdb0855
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/config/frontend/deployment.yaml
@@ -0,0 +1,28 @@
+apiVersion: apps/v1 # for k8s versions before 1.9.0 use apps/v1beta2 and before 1.8.0 use extensions/v1beta1
+kind: Deployment
+metadata:
+ name: frontend
+spec:
+ selector:
+ matchLabels:
+ app: guestbook
+ tier: frontend
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: guestbook
+ tier: frontend
+ spec:
+ containers:
+ - name: php-redis
+ image: "frontend"
+ resources:
+ requests:
+ cpu: 100m
+ memory: 100Mi
+ env:
+ - name: GET_HOSTS_FROM
+ value: env
+ ports:
+ - containerPort: 80
diff --git a/codelab/02_kpt-deploy/resources/sample-app/config/frontend/kustomization.yaml b/codelab/02_kpt-deploy/resources/sample-app/config/frontend/kustomization.yaml
new file mode 100644
index 00000000000..f4e19e73795
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/config/frontend/kustomization.yaml
@@ -0,0 +1,3 @@
+resources:
+- service.yaml
+- deployment.yaml
diff --git a/codelab/02_kpt-deploy/resources/sample-app/config/frontend/service.yaml b/codelab/02_kpt-deploy/resources/sample-app/config/frontend/service.yaml
new file mode 100644
index 00000000000..ba3471cbe6b
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/config/frontend/service.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: frontend
+ labels:
+ app: guestbook
+ tier: frontend
+spec:
+ type: LoadBalancer
+ ports:
+ - port: 80
+ selector:
+ app: guestbook
+ tier: frontend
diff --git a/codelab/02_kpt-deploy/resources/sample-app/config/kustomization.yaml b/codelab/02_kpt-deploy/resources/sample-app/config/kustomization.yaml
new file mode 100644
index 00000000000..909f989c694
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/config/kustomization.yaml
@@ -0,0 +1,2 @@
+resources:
+- frontend
diff --git a/codelab/02_kpt-deploy/resources/sample-app/php-redis/Dockerfile b/codelab/02_kpt-deploy/resources/sample-app/php-redis/Dockerfile
new file mode 100644
index 00000000000..46207880d6e
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/php-redis/Dockerfile
@@ -0,0 +1,30 @@
+# Copyright 2016 The Kubernetes Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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.
+
+FROM php:5-apache
+
+RUN apt-get update
+RUN pear channel-discover pear.nrk.io
+RUN pear install nrk/Predis
+
+# If the container's stdio is connected to systemd-journald,
+# /proc/self/fd/{1,2} are Unix sockets and apache will not be able to open()
+# them. Use "cat" to write directly to the already opened fds without opening
+# them again.
+RUN sed -i 's#ErrorLog /proc/self/fd/2#ErrorLog "|$/bin/cat 1>\&2"#' /etc/apache2/apache2.conf
+RUN sed -i 's#CustomLog /proc/self/fd/1 combined#CustomLog "|/bin/cat" combined#' /etc/apache2/apache2.conf
+
+ADD guestbook.php /var/www/html/guestbook.php
+ADD controllers.js /var/www/html/controllers.js
+ADD index.html /var/www/html/index.html
diff --git a/codelab/02_kpt-deploy/resources/sample-app/php-redis/Makefile b/codelab/02_kpt-deploy/resources/sample-app/php-redis/Makefile
new file mode 100644
index 00000000000..efd2dbd4b1c
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/php-redis/Makefile
@@ -0,0 +1,80 @@
+# Copyright 2017 The Kubernetes Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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.
+
+TAG = v6
+REGISTRY = gcr.io/yuwenma-gke-playground
+ARCH ?= $(shell go env GOARCH)
+ALL_ARCH = amd64 arm arm64 ppc64le
+
+QEMUVERSION=v2.7.0
+
+IMAGE = $(REGISTRY)/gb-frontend
+MULTI_ARCH_IMG = $(IMAGE)-$(ARCH)
+
+# Set default base image dynamically for each arch
+ifeq ($(ARCH),arm)
+ QEMUARCH=arm
+ BASEIMAGE=armhf/php:5.6-apache
+endif
+ifeq ($(ARCH),arm64)
+ QEMUARCH=aarch64
+ BASEIMAGE=arm64v8/php:5-apache
+endif
+ifeq ($(ARCH),ppc64le)
+ QEMUARCH=ppc64le
+ BASEIMAGE=ppc64le/php:5-apache
+endif
+
+TEMP_DIR := $(shell mktemp -d)
+
+all: all-container
+
+sub-container-%:
+ $(MAKE) ARCH=$* container
+
+sub-push-%:
+ $(MAKE) ARCH=$* push
+
+all-container: $(addprefix sub-container-,$(ALL_ARCH))
+
+all-push: $(addprefix sub-push-,$(ALL_ARCH))
+ docker manifest create --amend $(IMAGE):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(IMAGE)\-&:$(TAG)~g")
+ @for arch in $(ALL_ARCH); do docker manifest annotate --arch $${arch} ${IMAGE}:${TAG} ${IMAGE}-$${arch}:${TAG}; done
+ docker manifest push --purge ${IMAGE}:${TAG}
+
+container: .container-$(ARCH)
+.container-$(ARCH):
+ cp ./* $(TEMP_DIR)
+
+ifneq ($(ARCH),amd64)
+ cd $(TEMP_DIR) && sed -i "s|FROM php.*|FROM $(BASEIMAGE)\nCOPY qemu-$(QEMUARCH)-static /usr/bin\n|g" Dockerfile
+ # Register /usr/bin/qemu-ARCH-static as the handler for ARM binaries in the kernel
+ docker run --rm --privileged multiarch/qemu-user-static:register --reset
+ curl -sSL https://github.com/multiarch/qemu-user-static/releases/download/$(QEMUVERSION)/x86_64_qemu-$(QEMUARCH)-static.tar.gz | tar -xz -C $(TEMP_DIR)
+endif
+ docker build -t $(MULTI_ARCH_IMG):$(TAG) $(TEMP_DIR)
+
+ifeq ($(ARCH), amd64)
+ # This is for to maintain the backward compatibility
+ docker tag $(MULTI_ARCH_IMG):$(TAG) $(IMAGE):$(TAG)
+endif
+
+push: .push-$(ARCH)
+.push-$(ARCH): .container-$(ARCH)
+ docker push $(MULTI_ARCH_IMG):$(TAG)
+
+clean: $(addprefix sub-clean-,$(ALL_ARCH))
+ docker rmi -f $(IMAGE):$(TAG) || true
+sub-clean-%:
+ docker rmi -f $(IMAGE)-$*:$(TAG) || true
diff --git a/codelab/02_kpt-deploy/resources/sample-app/php-redis/controllers.js b/codelab/02_kpt-deploy/resources/sample-app/php-redis/controllers.js
new file mode 100644
index 00000000000..1e4b5504246
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/php-redis/controllers.js
@@ -0,0 +1,29 @@
+var redisApp = angular.module('redis', ['ui.bootstrap']);
+
+/**
+ * Constructor
+ */
+function RedisController() {}
+
+RedisController.prototype.onRedis = function() {
+ this.scope_.messages.push(this.scope_.msg);
+ this.scope_.msg = "";
+ var value = this.scope_.messages.join();
+ this.http_.get("guestbook.php?cmd=set&key=messages&value=" + value)
+ .success(angular.bind(this, function(data) {
+ this.scope_.redisResponse = "Updated.";
+ }));
+};
+
+redisApp.controller('RedisCtrl', function ($scope, $http, $location) {
+ $scope.controller = new RedisController();
+ $scope.controller.scope_ = $scope;
+ $scope.controller.location_ = $location;
+ $scope.controller.http_ = $http;
+
+ $scope.controller.http_.get("guestbook.php?cmd=get&key=messages")
+ .success(function(data) {
+ console.log(data);
+ $scope.messages = data.data.split(",");
+ });
+});
diff --git a/codelab/02_kpt-deploy/resources/sample-app/php-redis/guestbook.php b/codelab/02_kpt-deploy/resources/sample-app/php-redis/guestbook.php
new file mode 100644
index 00000000000..ee0670ee69f
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/php-redis/guestbook.php
@@ -0,0 +1,41 @@
+ 'tcp',
+ 'host' => $host,
+ 'port' => 6379,
+ ]);
+
+ $client->set($_GET['key'], $_GET['value']);
+ print('{"message": "Updated"}');
+ } else {
+ $host = 'redis-slave';
+ if (getenv('GET_HOSTS_FROM') == 'env') {
+ $host = getenv('REDIS_SLAVE_SERVICE_HOST');
+ }
+ $client = new Predis\Client([
+ 'scheme' => 'tcp',
+ 'host' => $host,
+ 'port' => 6379,
+ ]);
+
+ $value = $client->get($_GET['key']);
+ print('{"data": "' . $value . '"}');
+ }
+} else {
+ phpinfo();
+} ?>
diff --git a/codelab/02_kpt-deploy/resources/sample-app/php-redis/index.html b/codelab/02_kpt-deploy/resources/sample-app/php-redis/index.html
new file mode 100644
index 00000000000..b5f25f77b5b
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/php-redis/index.html
@@ -0,0 +1,25 @@
+
+
+ Hello World
+
+
+
+
+
+
+
+
+
diff --git a/codelab/02_kpt-deploy/resources/sample-app/skaffold.yaml b/codelab/02_kpt-deploy/resources/sample-app/skaffold.yaml
new file mode 100644
index 00000000000..9a9434a875c
--- /dev/null
+++ b/codelab/02_kpt-deploy/resources/sample-app/skaffold.yaml
@@ -0,0 +1,11 @@
+apiVersion: skaffold/v2beta8
+kind: Config
+metadata:
+ name: kpt-cl
+build:
+ artifacts:
+ - image: "frontend"
+ context: php-redis
+deploy:
+ kpt:
+ dir: config
diff --git a/hack/boilerplate/boilerplate.py b/hack/boilerplate/boilerplate.py
index 044d2a50f6a..3e6e1cdb062 100644
--- a/hack/boilerplate/boilerplate.py
+++ b/hack/boilerplate/boilerplate.py
@@ -23,7 +23,7 @@
import sys
-SKIPPED_DIRS = ["Godeps", "third_party", ".git", "vendor", "examples", "testdata", "node_modules"]
+SKIPPED_DIRS = ["Godeps", "third_party", ".git", "vendor", "examples", "testdata", "node_modules", "codelab"]
SKIPPED_FILES = ["install_golint.sh", "skaffold.pb.go", "skaffold.pb.gw.go", "build.sh", "statik.go"]
parser = argparse.ArgumentParser()