Full Code of skippbox/kubeless for AI

master af81a12a4b55 cached
273 files
24.9 MB
263.6k tokens
485 symbols
1 requests
Download .txt
Showing preview only (969K chars total). Download the full file or copy to clipboard to get everything.
Repository: skippbox/kubeless
Branch: master
Commit: af81a12a4b55
Files: 273
Total size: 24.9 MB

Directory structure:
gitextract_a4vhstu0/

├── .circleci/
│   └── config.yml
├── .github/
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── gcloud.json.enc
│   └── issue_template.md
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── OWNERS
├── README.md
├── cmd/
│   ├── function-controller/
│   │   └── function-controller.go
│   └── kubeless/
│       ├── autoscale/
│       │   ├── autoscale.go
│       │   ├── autoscaleCreate.go
│       │   ├── autoscaleDelete.go
│       │   ├── autoscaleList.go
│       │   ├── autoscaleList_test.go
│       │   └── autoscale_test.go
│       ├── completion/
│       │   └── completion.go
│       ├── function/
│       │   ├── call.go
│       │   ├── delete.go
│       │   ├── deploy.go
│       │   ├── describe.go
│       │   ├── function.go
│       │   ├── function_test.go
│       │   ├── list.go
│       │   ├── list_test.go
│       │   ├── logs.go
│       │   ├── top.go
│       │   ├── top_test.go
│       │   └── update.go
│       ├── getserverconfig/
│       │   └── getServerConfig.go
│       ├── kubeless.go
│       ├── topic/
│       │   ├── topic.go
│       │   ├── topicCreate.go
│       │   ├── topicDelete.go
│       │   ├── topicList.go
│       │   └── topicPublish.go
│       ├── trigger/
│       │   ├── cronjob/
│       │   │   ├── create.go
│       │   │   ├── cronjob_trigger.go
│       │   │   ├── delete.go
│       │   │   ├── list.go
│       │   │   └── update.go
│       │   ├── http/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── http_trigger.go
│       │   │   ├── list.go
│       │   │   └── update.go
│       │   ├── kafka/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── kafka_trigger.go
│       │   │   ├── list.go
│       │   │   └── update.go
│       │   ├── kinesis/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── kinesis_trigger.go
│       │   │   ├── list.go
│       │   │   ├── publish.go
│       │   │   ├── stream_create.go
│       │   │   └── update.go
│       │   ├── nats/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── list.go
│       │   │   ├── nats_trigger.go
│       │   │   ├── publish.go
│       │   │   └── update.go
│       │   └── trigger.go
│       └── version/
│           └── version.go
├── docker/
│   ├── controller-manager
│   ├── dev-environment/
│   │   ├── Dockerfile
│   │   └── entry-point.sh
│   ├── event-sources/
│   │   └── kubernetes/
│   │       ├── Dockerfile
│   │       ├── README.md
│   │       └── events.py
│   ├── function-controller/
│   │   └── Dockerfile
│   ├── function-image-builder/
│   │   ├── Dockerfile
│   │   └── entrypoint.sh
│   ├── runtime/
│   │   └── README.md
│   └── unzip/
│       └── Dockerfile
├── docs/
│   ├── GKE-deployment.md
│   ├── README.md
│   ├── advanced-function-deployment.md
│   ├── architecture.md
│   ├── autoscaling.md
│   ├── building-functions.md
│   ├── cronjob-triggers.md
│   ├── debug-functions.md
│   ├── debugging.md
│   ├── dev-guide.md
│   ├── function-controller-configuration.md
│   ├── http-triggers.md
│   ├── implementing-new-runtime.md
│   ├── implementing-new-trigger.md
│   ├── kubeless-functions.md
│   ├── kubeless-on-AKS.md
│   ├── misc/
│   │   ├── kafka-pv-gke.yaml
│   │   ├── kubeless-grafana-dashboard.json
│   │   └── zookeeper-pv-gke.yaml
│   ├── monitoring.md
│   ├── proposals/
│   │   ├── decoupling-triggers-and-runtimes.md
│   │   └── http-triggers.md
│   ├── pubsub-functions.md
│   ├── quick-start.md
│   ├── release-flow.md
│   ├── runtimes.md
│   ├── streaming-functions.md
│   ├── triggers.md
│   ├── troubleshooting.md
│   └── use-existing-kafka.md
├── examples/
│   ├── Makefile
│   ├── README.md
│   ├── ballerina/
│   │   ├── hello_with_conf/
│   │   │   ├── hello_with_conf.bal
│   │   │   └── kubeless.toml
│   │   ├── helloget.bal
│   │   └── hellowithdata.bal
│   ├── dotnetcore/
│   │   ├── dependency-yaml.cs
│   │   ├── dependency-yaml.csproj
│   │   ├── fibonacci.cs
│   │   ├── fibonacci.csproj
│   │   ├── helloget.cs
│   │   ├── helloget.csproj
│   │   ├── hellowithdata.cs
│   │   └── hellowithdata.csproj
│   ├── golang/
│   │   ├── go.mod
│   │   ├── helloget.go
│   │   ├── hellowithdata.go
│   │   └── hellowithdeps.go
│   ├── java/
│   │   ├── HelloGet.java
│   │   ├── HelloWithData.java
│   │   ├── HelloWithDeps.java
│   │   └── pom.xml
│   ├── jvm/
│   │   ├── Readme.md
│   │   ├── java/
│   │   │   ├── Readme.md
│   │   │   ├── build/
│   │   │   │   └── libs/
│   │   │   │       └── java-0.1-all.jar
│   │   │   ├── build.gradle
│   │   │   ├── src/
│   │   │   │   └── main/
│   │   │   │       └── java/
│   │   │   │           └── io/
│   │   │   │               └── ino/
│   │   │   │                   └── Handler.java
│   │   │   └── test-java-jvm.jar
│   │   └── scala/
│   │       ├── Readme.md
│   │       ├── build.sbt
│   │       ├── project/
│   │       │   ├── assembly.sbt
│   │       │   └── build.properties
│   │       └── src/
│   │           └── main/
│   │               └── scala/
│   │                   └── de/
│   │                       └── inoio/
│   │                           └── Handler.scala
│   ├── nodejs/
│   │   ├── function.yaml
│   │   ├── function1.yaml
│   │   ├── helloFunctions.tar.bz2
│   │   ├── helloFunctions.tar.xz
│   │   ├── helloget.js
│   │   ├── hellostream.js
│   │   ├── hellowithdata.js
│   │   ├── hellowithdeps.js
│   │   ├── index.js
│   │   └── package.json
│   ├── php/
│   │   ├── composer.json
│   │   ├── helloget.php
│   │   ├── hellowithdata.php
│   │   └── hellowithdeps.php
│   ├── python/
│   │   ├── Dockerfile
│   │   ├── function.yaml
│   │   ├── function1.yaml
│   │   ├── helloget.py
│   │   ├── hellowithdata.py
│   │   ├── hellowithdeps.py
│   │   ├── hellowithdepshelper.py
│   │   └── requirements.txt
│   └── ruby/
│       ├── Gemfile
│       ├── function.yaml
│       ├── helloget.rb
│       ├── hellowithdata.rb
│       ├── hellowithdeps.rb
│       └── latest.rb
├── go.mod
├── go.sum
├── hack/
│   ├── boilerplate.go.txt
│   └── update-codegen.sh
├── kubeless-non-rbac.jsonnet
├── kubeless-openshift.jsonnet
├── kubeless.jsonnet
├── manifests/
│   ├── README.md
│   ├── autoscaling/
│   │   ├── custom-metrics.yaml
│   │   ├── prometheus-operator.yaml
│   │   ├── sample-metrics-app.yaml
│   │   └── sample-prometheus-instance.yaml
│   ├── kinesis/
│   │   └── kinesalite.yaml
│   ├── monitoring/
│   │   ├── grafana-configmap.yaml
│   │   ├── grafana-deployment.yaml
│   │   ├── grafana-job.yaml
│   │   ├── grafana-service.yaml
│   │   └── prometheus.yaml
│   ├── nats/
│   │   └── nats-cluster.yaml
│   └── ui/
│       └── README.md
├── pkg/
│   ├── apis/
│   │   └── kubeless/
│   │       ├── register.go
│   │       └── v1beta1/
│   │           ├── doc.go
│   │           ├── function.go
│   │           ├── register.go
│   │           └── zz_generated.deepcopy.go
│   ├── client/
│   │   ├── clientset/
│   │   │   └── versioned/
│   │   │       ├── clientset.go
│   │   │       ├── doc.go
│   │   │       ├── fake/
│   │   │       │   ├── clientset_generated.go
│   │   │       │   ├── doc.go
│   │   │       │   └── register.go
│   │   │       ├── scheme/
│   │   │       │   ├── doc.go
│   │   │       │   └── register.go
│   │   │       └── typed/
│   │   │           └── kubeless/
│   │   │               └── v1beta1/
│   │   │                   ├── doc.go
│   │   │                   ├── fake/
│   │   │                   │   ├── doc.go
│   │   │                   │   ├── fake_function.go
│   │   │                   │   └── fake_kubeless_client.go
│   │   │                   ├── function.go
│   │   │                   ├── generated_expansion.go
│   │   │                   └── kubeless_client.go
│   │   ├── informers/
│   │   │   └── externalversions/
│   │   │       ├── factory.go
│   │   │       ├── generic.go
│   │   │       ├── internalinterfaces/
│   │   │       │   └── factory_interfaces.go
│   │   │       └── kubeless/
│   │   │           ├── interface.go
│   │   │           └── v1beta1/
│   │   │               ├── function.go
│   │   │               └── interface.go
│   │   └── listers/
│   │       └── kubeless/
│   │           └── v1beta1/
│   │               ├── expansion_generated.go
│   │               └── function.go
│   ├── controller/
│   │   ├── function_controller.go
│   │   └── function_controller_test.go
│   ├── function-image-builder/
│   │   ├── image_builder.go
│   │   └── layer-builder/
│   │       ├── description.go
│   │       ├── description_test.go
│   │       ├── layer.go
│   │       ├── layer_builder.go
│   │       ├── layer_test.go
│   │       ├── manifest.go
│   │       └── manifest_test.go
│   ├── function-proxy/
│   │   ├── Gopkg.toml
│   │   ├── proxy.go
│   │   └── utils/
│   │       └── proxy-utils.go
│   ├── functions/
│   │   └── params.go
│   ├── langruntime/
│   │   ├── langruntime.go
│   │   ├── langruntime_test.go
│   │   └── langruntimetestutils.go
│   ├── registry/
│   │   ├── registry.go
│   │   └── registry_test.go
│   ├── utils/
│   │   ├── configlocation.go
│   │   ├── exec.go
│   │   ├── exec_test.go
│   │   ├── k8sutil.go
│   │   ├── k8sutil_test.go
│   │   ├── kubelessutil.go
│   │   ├── kubelessutil_test.go
│   │   └── metrics.go
│   └── version/
│       └── version.go
├── script/
│   ├── .validate
│   ├── binary
│   ├── binary-cli
│   ├── binary-controller
│   ├── cluster-up-minikube.sh
│   ├── create_release.sh
│   ├── enable-gcloud.sh
│   ├── find_digest.sh
│   ├── integration-tests
│   ├── libtest.bash
│   ├── pull-or-build-image.sh
│   ├── release_utils.sh
│   ├── start-gke-env.sh
│   ├── start-test-environment.sh
│   ├── upload_release_notes.sh
│   ├── validate-git-marks
│   ├── validate-gofmt
│   ├── validate-lint
│   ├── validate-test
│   └── validate-vet
└── tests/
    ├── deployment-tests.bats
    ├── integration-tests-cronjob.bats
    ├── integration-tests-http.bats
    ├── integration-tests-kafka.bats
    ├── integration-tests-kinesis.bats
    ├── integration-tests-nats.bats
    ├── integration-tests-prebuilt.bats
    └── integration-tests.bats

================================================
FILE CONTENTS
================================================

================================================
FILE: .circleci/config.yml
================================================
version: 2

## Definitions
build_allways: &build_allways
  filters:
    tags:
      only: /.*/
defaults: &defaults
  environment:
    CONTROLLER_IMAGE_NAME: kubeless/function-controller
    BUILDER_IMAGE_NAME: kubeless/function-image-builder
    CGO_ENABLED: "0"
    TEST_DEBUG: "1"
    GKE_VERSION: 1.12
    MINIKUBE_VERSION: v1.2.0
    MANIFESTS: kubeless kubeless-non-rbac kubeless-openshift
exports: &exports
  # It is not possible to resolve env vars in the environment section:
  # https://discuss.circleci.com/t/using-environment-variables-in-config-yml-not-working/14237
  run: |
    CONTROLLER_TAG=${CIRCLE_TAG:-build-$CIRCLE_WORKFLOW_ID}
    echo "export CONTROLLER_TAG=${CONTROLLER_TAG}" >> $BASH_ENV
    echo "export CONTROLLER_IMAGE=${CONTROLLER_IMAGE_NAME}:${CONTROLLER_TAG}" >> $BASH_ENV
    echo "export FUNCTION_IMAGE_BUILDER=${BUILDER_IMAGE_NAME}:${CONTROLLER_TAG}" >> $BASH_ENV
    echo "export KUBECFG_JPATH=/home/circleci/src/github.com/kubeless/kubeless/ksonnet-lib" >> $BASH_ENV
    echo "export PATH=$(pwd)/bats/libexec:$GOPATH/bin:$PATH" >> $BASH_ENV
    echo "export GIT_SHA1=${CIRCLE_SHA1}" >> $BASH_ENV
restore_workspace: &restore_workspace
  run: |
    make bootstrap
    sudo cp -r /tmp/go/bin/* /usr/local/bin/
    cp -r /tmp/go/*yaml .
#### End of definitions

workflows:
  version: 2
  kubeless:
    jobs:
      - build:
          <<: *build_allways
      - minikube:
          <<: *build_allways
          requires:
            - build
      - build-cross-binaries:
          <<: *build_allways
          requires:
            - build
      - minikube_build_functions:
          <<: *build_allways
          requires:
            - build
      - GKE:
          <<: *build_allways
          requires:
            - build
      - push_latest_images:
          filters:
            branches:
              only: master
          requires:
            - minikube
            - minikube_build_functions
            - GKE
      - release:
          filters:
            tags:
              only: /v.*/
            branches:
              ignore: /.*/
          requires:
            - minikube
            - minikube_build_functions
            - GKE
jobs:
  build:
    <<: *defaults
    docker:
      - image: circleci/golang:1.15
    steps:
      - checkout
      - restore_cache:
          keys:
            - go-mod-v4-{{ checksum "go.sum" }}
      - <<: *exports
      - run: go mod download
      - run: make bootstrap
      - run: make VERSION=${CONTROLLER_TAG} binary
      - run: make test
      - run: make validation
      - run: make all-yaml
      - run: |
          mkdir build-manifests
          IFS=' ' read -r -a manifests <<< "$MANIFESTS"
          for f in "${manifests[@]}"; do
            sed -i.bak 's/:latest/'":${CONTROLLER_TAG}"'/g' ${f}.yaml
            cp ${f}.yaml build-manifests/
          done
      - persist_to_workspace:
          root: /go
          paths:
            - ./bin
      - persist_to_workspace:
          root: ./
          paths:
            - ./*yaml
      - store_artifacts:
          path: /go/bin/kubeless
          destination: ./bin/kubeless
      - store_artifacts:
          path: ./build-manifests/
      - save_cache:
          key: go-mod-v4-{{ checksum "go.sum" }}
          paths:
            - /go/pkg/mod
  minikube:
    <<: *defaults
    machine:
      image: ubuntu-1604:202007-01
    steps:
      - checkout
      - run: sudo apt-get update -y
      - run: sudo apt-get install -y tar gzip bzip2 xz-utils
      - attach_workspace:
          at: /tmp/go
      - <<: *exports
      - <<: *restore_workspace
      - run: ./script/pull-or-build-image.sh function-controller
      - run: ./script/integration-tests minikube deployment
      - run: ./script/integration-tests minikube basic
  build-cross-binaries:
    <<: *defaults
    docker:
      - image: circleci/golang:1.15
    steps:
      - <<: *exports
      - checkout
      - attach_workspace:
          at: /tmp/go
      - <<: *restore_workspace
      - run: make VERSION=${CIRCLE_TAG} binary-cross
      - store_artifacts:
          path: bundles
  minikube_build_functions:
    <<: *defaults
    machine:
      image: ubuntu-1604:202007-01
    steps:
      - checkout
      - <<: *exports
      - attach_workspace:
          at: /tmp/go
      - <<: *restore_workspace
      - run: ./script/pull-or-build-image.sh function-controller
      - run: ./script/pull-or-build-image.sh function-image-builder
      - run: "echo '{\"insecure-registries\" : [\"0.0.0.0/0\"]}' > /tmp/daemon.json"
      - run: sudo mv /tmp/daemon.json /etc/docker/daemon.json
      - run: sudo service docker restart
      - run: docker info
      - run: docker run -d -p 5000:5000 --restart=always --name registry -v /data/docker-registry:/var/lib/registry registry:2
      - run: "sed -i.bak 's/enable-build-step: \"false\"/enable-build-step: \"true\"/g' kubeless.yaml"
      - run: "sed -i.bak 's/function-registry-tls-verify: \"true\"/function-registry-tls-verify: \"false\"/g' kubeless.yaml"
      - run: ./script/integration-tests minikube deployment
      - run: ./script/integration-tests minikube prebuilt_functions
  GKE:
    <<: *defaults
    docker:
      - image: circleci/golang:1.15
    steps:
      - run: |
          # In case of GKE we will only want to build if it is
          # a build of a branch in the kubeless/kubeless repository
          if [[ -n "$GKE_ADMIN" && -z "$CIRCLE_PULL_REQUESTS" ]]; then
            export SHOULD_TEST=1
          fi
          if [[ "$SHOULD_TEST" != "1" ]]; then
            circleci step halt
          fi
      - checkout
      - <<: *exports
      - attach_workspace:
          at: /tmp/go
      - <<: *restore_workspace
      - setup_remote_docker
      - run: ./script/enable-gcloud.sh $(pwd) > /dev/null
      - run: echo "export ESCAPED_GKE_CLUSTER=$(echo ${GKE_CLUSTER}-ci-${CIRCLE_BRANCH:-$CIRCLE_TAG} | sed 's/[^a-z0-9-]//g')" >> $BASH_ENV
      - run: ./script/start-gke-env.sh $ESCAPED_GKE_CLUSTER $ZONE $GKE_VERSION $GKE_ADMIN > /dev/null
      - run: ./script/pull-or-build-image.sh function-controller
      - run: ./script/integration-tests gke_${GKE_PROJECT}_${ZONE}_${ESCAPED_GKE_CLUSTER} deployment
      - run: ./script/integration-tests gke_${GKE_PROJECT}_${ZONE}_${ESCAPED_GKE_CLUSTER} basic
      - run: ./script/integration-tests gke_${GKE_PROJECT}_${ZONE}_${ESCAPED_GKE_CLUSTER} cronjob
  push_latest_images:
    <<: *defaults
    docker:
      - image: circleci/golang:1.15
    steps:
      - <<: *exports
      - setup_remote_docker
      - run: docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"   
      - run: |
          images=( 
            $CONTROLLER_IMAGE_NAME
            $BUILDER_IMAGE_NAME 
          )
          for image in "${images[@]}"; do
            echo "Pulling ${image}:${CONTROLLER_TAG}"
            docker pull ${image}:${CONTROLLER_TAG}
            docker tag ${image}:${CONTROLLER_TAG} ${image}:latest
            docker push ${image}:latest
          done
  release:
    <<: *defaults
    docker:
      - image: circleci/golang:1.15
    steps:
      - <<: *exports
      - checkout
      - attach_workspace:
          at: /tmp/go
      - <<: *restore_workspace
      - run: make VERSION=${CIRCLE_TAG} binary-cross
      - run: for d in bundles/kubeless_*; do zip -r9 $d.zip $d/; done
      - run: ./script/create_release.sh ${CIRCLE_TAG} "${MANIFESTS}"


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
**Issue Ref**: [Issue number related to this PR or None]
 
**Description**: 

[PR Description]

**TODOs**:
 - [ ] Ready to review
 - [ ] Automated Tests
 - [ ] Docs


================================================
FILE: .github/issue_template.md
================================================
**Is this a BUG REPORT or FEATURE REQUEST?**:

**What happened**:

**What you expected to happen**:

**How to reproduce it (as minimally and precisely as possible)**:

**Anything else we need to know?**:

**Environment**:
- Kubernetes version (use `kubectl version`):
- Kubeless version (use `kubeless version`):
- Cloud provider or physical cluster:


================================================
FILE: .gitignore
================================================
### Go ###
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

### Linux ###
*~

# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*

# KDE directory preferences
.directory

# Linux trash folder which might appear on any partition or disk
.Trash-*

# .nfs files are created when an open file is removed but is still being accessed
.nfs*

### OSX ###
*.DS_Store
.AppleDouble
.LSOverride

### vscode ###
.vscode/

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Vim ###
# swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# session
Session.vim
# temporary
.netrwhist
# auto-generated tag files
tags


## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/

# JVM
.classpath
.project
.settings

# Visual Studio 2015 cache/options directory
.vs/

# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json

*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc

# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets

# IDEA Files
.idea/
*.iml
*.ipr
*.iws

# Kubeless specific
bats/
bundles/
docker/function-controller/kubeless-function-controller
docker/function-image-builder/imbuilder
ksonnet-lib/
kubeless-openshift.yaml
kubeless-non-rbac.yaml
kubeless.yaml
kafka-zookeeper.yaml
kafka-zookeeper-openshift.yaml
nats.yaml
kinesis.yaml


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kubernetes@bitnami.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing Guidelines

## License and CLA

The Kubeless license is Apache Software License V2

We do not currently ask for a Contributor License Agreement to be signed.

## Support Channels

Whether you are a user or contributor, official support channels include:

- GitHub [issues](https://github.com/kubeless/kubeless/issues/new)
- Slack: #kubeless room in the [Kubernetes Slack](http://slack.k8s.io/)

Before opening a new issue or submitting a new pull request, it's helpful to search the project - it's likely that another user has already reported the issue you're facing, or it's a known issue that we're already aware of.

## How to become a contributor and submit your own code

### Setup your development environment

Consult the [Developer's guide](./docs/dev-guide.md) to setup yourself up.

### Contributing a patch

1. Submit an issue describing your proposed change to the repo in question.
2. The [repo owners](OWNERS) will respond to your issue promptly.
3. If your proposed change is accepted, fork the desired repo, develop and test your code changes.
4. Submit a pull request making sure you fill up clearly the description, point out the particular
   issue your PR is mitigating, and ask for code review. If the PR is related to Kafka, include at least the tag [Kafka] in the title. You will be asked to add tests (either unit or e2e tests depending on the patch) and update any affected documentation.

## Issues

Issues are used as the primary method for tracking anything to do with the Kubeless project.

### Issue Type

* Question: These are support or functionality inquiries that we want to have a record of for future reference. Generally these are questions that are too complex or large to store in the Slack channel or have particular interest to the community as a whole. Depending on the discussion, these can turn into "Feature" or "Bug" issues.
* Proposal: Used for items (like this one) that propose a new ideas or functionality that require a larger community discussion. This allows for feedback from others in the community before a feature is actually developed. This is not needed for small additions. Final word on whether or not a feature needs a proposal is up to the core maintainers. All issues that are proposals should both have a label and an issue title of "Proposal: [the rest of the title]." A proposal can become a "Feature" and does not require a milestone.
* Features: These track specific feature requests and ideas until they are complete. They can evolve from a "Proposal" or can be submitted individually depending on the size.
* Bugs: These track bugs with the code or problems with the documentation (i.e. missing or incomplete)




================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright (c) 2016-2017 Bitnami

   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.


================================================
FILE: Makefile
================================================
GO = go
GO_FLAGS =
GOFMT = gofmt
KUBECFG = kubecfg
DOCKER = docker
CONTROLLER_IMAGE = kubeless-function-controller:latest
FUNCTION_IMAGE_BUILDER = kubeless-function-image-builder:latest
OS = linux
ARCH = amd64
BUNDLES = bundles
GO_PACKAGES = ./cmd/... ./pkg/...
GO_FILES := $(shell find $(shell $(GO) list -f '{{.Dir}}' $(GO_PACKAGES)) -name \*.go)

export KUBECFG_JPATH := $(CURDIR)/ksonnet-lib
export PATH := $(PATH):$(CURDIR)/bats/bin

.PHONY: all

KUBELESS_ENVS := \
	-e OS_PLATFORM_ARG \
	-e OS_ARCH_ARG \

default: binary

binary:
	CGO_ENABLED=0 ./script/binary

binary-cross:
	./script/binary-cli


%.yaml: %.jsonnet
	$(KUBECFG) show -U https://raw.githubusercontent.com/kubeless/runtimes/master -o yaml $< > $@.tmp
	mv $@.tmp $@

all-yaml: kubeless.yaml kubeless-non-rbac.yaml kubeless-openshift.yaml

kubeless.yaml: kubeless.jsonnet kubeless-non-rbac.jsonnet

kubeless-non-rbac.yaml: kubeless-non-rbac.jsonnet

kubeless-openshift.yaml: kubeless-openshift.jsonnet

docker/function-controller: controller-build
	cp $(BUNDLES)/kubeless_$(OS)-$(ARCH)/kubeless-function-controller $@

controller-build:
	./script/binary-controller -os=$(OS) -arch=$(ARCH)

function-controller: docker/function-controller
	$(DOCKER) build -t $(CONTROLLER_IMAGE) $<

docker/function-image-builder: function-image-builder-build
	cp $(BUNDLES)/kubeless_$(OS)-$(ARCH)/imbuilder $@

function-image-builder-build:
	./script/binary-controller -os=$(OS) -arch=$(ARCH) imbuilder github.com/kubeless/kubeless/pkg/function-image-builder

function-image-builder: docker/function-image-builder
	$(DOCKER) build -t $(FUNCTION_IMAGE_BUILDER) $<

update:
	./hack/update-codegen.sh

test:
	$(GO) test $(GO_FLAGS) $(GO_PACKAGES)

validation:
	./script/validate-lint
	./script/validate-gofmt
	./script/validate-git-marks

integration-tests:
	./script/integration-tests minikube deployment
	./script/integration-tests minikube basic

fmt:
	$(GOFMT) -s -w $(GO_FILES)

bats:
	git clone --branch=v0.4.0 --depth=1 https://github.com/sstephenson/bats.git

ksonnet-lib:
	git clone --depth=1 https://github.com/ksonnet/ksonnet-lib.git

.PHONY: bootstrap
bootstrap: bats ksonnet-lib

	GO111MODULE="off" go get -u github.com/mitchellh/gox
	GO111MODULE="off" go get -u golang.org/x/lint/golint

	@if ! which kubecfg >/dev/null; then \
	sudo wget -q -O /usr/local/bin/kubecfg https://github.com/ksonnet/kubecfg/releases/download/v0.9.0/kubecfg-$$(go env GOOS)-$$(go env GOARCH); \
	sudo chmod +x /usr/local/bin/kubecfg; \
	fi

	@if ! which kubectl >/dev/null; then \
	KUBECTL_VERSION=$$(wget -qO- https://storage.googleapis.com/kubernetes-release/release/stable.txt); \
	sudo wget -q -O /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$$KUBECTL_VERSION/bin/$$(go env GOOS)/$$(go env GOARCH)/kubectl; \
	sudo chmod +x /usr/local/bin/kubectl; \
	fi


================================================
FILE: OWNERS
================================================
Kubeless - A Bitnami Project

Engineering manager:
  - ppbaena

Emeritus maintainers:
  - ngtuna
  - andresmgot
  - anguslees
  - sebgoa



================================================
FILE: README.md
================================================
# <img src="https://cloud.githubusercontent.com/assets/4056725/25480209/1d5bf83c-2b48-11e7-8db8-bcd650f31297.png" alt="Kubeless logo" width="400">

[![CircleCI](https://circleci.com/gh/kubeless/kubeless.svg?style=svg)](https://circleci.com/gh/kubeless/kubeless)
[![Slack](https://img.shields.io/badge/slack-join%20chat%20%E2%86%92-e01563.svg)](http://slack.k8s.io)
[![Not Maintained](https://img.shields.io/badge/Maintenance%20Level-Not%20Maintained-yellow.svg)](https://gist.github.com/cheerfulstoic/d107229326a01ff0f333a1d3476e068d)

## WARNING: Kubeless is no longer actively maintained by VMware.

VMware has made the difficult decision to stop driving this project and therefore we will no longer actively respond to issues or pull requests. If you would like to take over maintaining this project independently from VMware, please let us know so we can add a link to your forked project here.

Thank You.

## Overview

`kubeless` is a Kubernetes-native serverless framework that lets you deploy small bits of code without having to worry about the underlying infrastructure plumbing. It leverages Kubernetes resources to provide auto-scaling, API routing, monitoring, troubleshooting and more.

Kubeless stands out as we use a [Custom Resource Definition](https://kubernetes.io/docs/tasks/access-kubernetes-api/extend-api-custom-resource-definitions/) to be able to create functions as custom kubernetes resources. We then run an in-cluster controller that watches these custom resources and launches _runtimes_ on-demand. The controller dynamically injects the functions code into the runtimes and make them available over HTTP or via a PubSub mechanism.

Kubeless is purely open-source and non-affiliated to any commercial organization. Chime in at anytime, we would love the help and feedback !

## Tools

- A [UI](https://github.com/kubeless/kubeless-ui) is available. It can run locally or in-cluster.
- A [serverless framework plugin](https://github.com/serverless/serverless-kubeless) is available.

## Quick start

Check out the instructions for quickly set up Kubeless [here](http://kubeless.io/docs/quick-start).

## Building

Consult the [developer's guide](docs/dev-guide.md) for a complete set of instruction
to build kubeless.

## Compatibility Matrix with Kubernetes

Kubeless fully supports Kubernetes versions greater than 1.9 (tested until 1.15). For other versions some of the features in Kubeless may not be available. Our CI run tests against two different platforms: GKE (1.12) and Minikube (1.15). Other platforms are supported but fully compatibiliy cannot be assured.

## _Roadmap_

We would love to get your help, feel free to lend a hand. We are currently looking to implement the following high level features:

- Add other runtimes, currently Golang, Python, NodeJS, Ruby, PHP, .NET and Ballerina are supported. We are also providing a way to use custom runtime. Please check [this doc](./docs/runtimes.md) for more details.
- Investigate other messaging bus (e.g SQS, rabbitMQ)
- Optimize for functions startup time
- Add distributed tracing (maybe using istio)

## Community

**Issues**: If you find any issues, please [file it](https://github.com/kubeless/kubeless/issues).

**Slack**: We're fairly active on [slack](http://slack.k8s.io) and you can find us in the #kubeless channel.


================================================
FILE: cmd/function-controller/function-controller.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

// Kubeless controller binary.
//
// See github.com/kubeless/kubeless/tree/master/pkg/controller
package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	monitoringv1alpha1 "github.com/coreos/prometheus-operator/pkg/client/monitoring/v1alpha1"
	"github.com/kubeless/kubeless/pkg/controller"
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/kubeless/kubeless/pkg/version"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

const (
	globalUsage = `` //TODO: adding explanation
)

var rootCmd = &cobra.Command{
	Use:   "kubeless-controller",
	Short: "Kubeless controller",
	Long:  globalUsage,
	Run: func(cmd *cobra.Command, args []string) {
		kubelessClient, err := utils.GetFunctionClientInCluster()
		if err != nil {
			logrus.Fatalf("Cannot get kubeless client: %v", err)
		}

		functionCfg := controller.Config{
			KubeCli:        utils.GetClient(),
			FunctionClient: kubelessClient,
		}

		restCfg, err := utils.GetInClusterConfig()
		if err != nil {
			logrus.Fatalf("Cannot get REST client: %v", err)
		}
		// ServiceMonitor client is needed for handling monitoring resources
		smclient, err := monitoringv1alpha1.NewForConfig(restCfg)
		if err != nil {
			logrus.Fatal(err)
		}

		functionController := controller.NewFunctionController(functionCfg, smclient)

		stopCh := make(chan struct{})
		defer close(stopCh)

		go functionController.Run(stopCh)

		sigterm := make(chan os.Signal, 1)
		signal.Notify(sigterm, syscall.SIGTERM)
		signal.Notify(sigterm, syscall.SIGINT)
		<-sigterm
	},
}

func main() {
	logrus.Infof("Running Kubeless controller manager version: %v", version.Version)
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}


================================================
FILE: cmd/kubeless/autoscale/autoscale.go
================================================
/*
Copyright 2016 Skippbox, Ltd.
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.
*/

package autoscale

import (
	"fmt"
	"strconv"

	"github.com/spf13/cobra"
	"k8s.io/api/autoscaling/v2beta1"
	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// AutoscaleCmd contains first-class command for autoscale
var AutoscaleCmd = &cobra.Command{
	Use:   "autoscale SUBCOMMAND",
	Short: "manage autoscale to function on Kubeless",
	Long:  `autoscale command allows user to list, create, delete autoscale rule for function on Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cmd.Help()
	},
}

func init() {
	cmds := []*cobra.Command{autoscaleCreateCmd, autoscaleListCmd, autoscaleDeleteCmd}

	for _, cmd := range cmds {
		AutoscaleCmd.AddCommand(cmd)
		cmd.Flags().StringP("namespace", "n", "", "Specify namespace for the autoscale")

	}
}

func getHorizontalAutoscaleDefinition(name, ns, metric string, min, max int32, value string, labels map[string]string) (v2beta1.HorizontalPodAutoscaler, error) {
	m := []v2beta1.MetricSpec{}
	switch metric {
	case "cpu":
		i, err := strconv.ParseInt(value, 10, 32)
		if err != nil {
			return v2beta1.HorizontalPodAutoscaler{}, err
		}
		i32 := int32(i)
		m = []v2beta1.MetricSpec{
			{
				Type: v2beta1.ResourceMetricSourceType,
				Resource: &v2beta1.ResourceMetricSource{
					Name:                     v1.ResourceCPU,
					TargetAverageUtilization: &i32,
				},
			},
		}
	case "qps":
		q, err := resource.ParseQuantity(value)
		if err != nil {
			return v2beta1.HorizontalPodAutoscaler{}, err
		}
		m = []v2beta1.MetricSpec{
			{
				Type: v2beta1.ObjectMetricSourceType,
				Object: &v2beta1.ObjectMetricSource{
					MetricName:  "function_calls",
					TargetValue: q,
					Target: v2beta1.CrossVersionObjectReference{
						Kind: "Service",
						Name: name,
					},
				},
			},
		}
		if err != nil {
			return v2beta1.HorizontalPodAutoscaler{}, err
		}
	default:
		return v2beta1.HorizontalPodAutoscaler{}, fmt.Errorf("metric %s is not supported", metric)
	}

	return v2beta1.HorizontalPodAutoscaler{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "autoscaling/v2beta1",
			Kind:       "HorizontalPodAutoscaler",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      name,
			Namespace: ns,
			Labels:    labels,
		},
		Spec: v2beta1.HorizontalPodAutoscalerSpec{
			ScaleTargetRef: v2beta1.CrossVersionObjectReference{
				APIVersion: "apps/v1beta1",
				Kind:       "Deployment",
				Name:       name,
			},
			MinReplicas: &min,
			MaxReplicas: max,
			Metrics:     m,
		},
	}, nil
}


================================================
FILE: cmd/kubeless/autoscale/autoscaleCreate.go
================================================
package autoscale

import (
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

var autoscaleCreateCmd = &cobra.Command{
	Use:   "create <name> FLAG",
	Short: "automatically scale function based on monitored metrics",
	Long:  `automatically scale function based on monitored metrics`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - function name")
		}
		funcName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		function, err := utils.GetFunction(funcName, ns)
		if err != nil {
			logrus.Fatalf("Unable to find the function %s. Received %s: ", funcName, err)
		}

		min, err := cmd.Flags().GetInt32("min")
		if err != nil {
			logrus.Fatal(err)
		} else if min <= 0 {
			logrus.Fatalf("min can't be negative or zero")
		}
		max, err := cmd.Flags().GetInt32("max")
		if err != nil {
			logrus.Fatal(err)
		} else if max < min {
			logrus.Fatalf("max must be greater than or equal to min")
		}

		metric, err := cmd.Flags().GetString("metric")
		if err != nil {
			logrus.Fatal(err)
		}
		if metric != "cpu" && metric != "qps" {
			logrus.Fatalf("only supported metrics: cpu, qps")
		}

		value, err := cmd.Flags().GetString("value")
		if err != nil {
			logrus.Fatal(err)
		}

		hpa, err := getHorizontalAutoscaleDefinition(funcName, ns, metric, min, max, value, function.ObjectMeta.Labels)
		if err != nil {
			logrus.Fatal(err)
		}
		function.Spec.HorizontalPodAutoscaler = hpa

		kubelessClient, err := utils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatal(err)
		}
		logrus.Infof("Adding autoscaling rule to the function...")
		err = utils.UpdateFunctionCustomResource(kubelessClient, &function)
		if err != nil {
			logrus.Fatal(err)
		}
		logrus.Infof("Autoscaling rule for %s submitted for deployment", funcName)
	},
}

func init() {
	autoscaleCreateCmd.Flags().Int32("min", 1, "minimum number of replicas")
	autoscaleCreateCmd.Flags().Int32("max", 1, "maximum number of replicas")
	autoscaleCreateCmd.Flags().String("metric", "cpu", "metric to use for calculating the autoscale. Supported metrics: cpu, qps")
	autoscaleCreateCmd.Flags().String("value", "", "value of the average of the metric across all replicas. If metric is cpu, value is a number represented as percentage. If metric is qps, value must be in format of Quantity")
	autoscaleCreateCmd.MarkFlagRequired("value")
}


================================================
FILE: cmd/kubeless/autoscale/autoscaleDelete.go
================================================
/*
Copyright 2016 Skippbox, Ltd.
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.
*/

package autoscale

import (
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/api/autoscaling/v2beta1"
)

var autoscaleDeleteCmd = &cobra.Command{
	Use:   "delete <name>",
	Short: "delete an autoscale from Kubeless",
	Long:  `delete an autoscale from Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - autoscale name")
		}
		funcName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		function, err := utils.GetFunction(funcName, ns)
		if err != nil {
			logrus.Fatalf("Unable to find the function %s. Received %s: ", funcName, err)
		}

		if function.Spec.HorizontalPodAutoscaler.Name != "" {
			function.Spec.HorizontalPodAutoscaler = v2beta1.HorizontalPodAutoscaler{}
			kubelessClient, err := utils.GetKubelessClientOutCluster()
			if err != nil {
				logrus.Fatal(err)
			}
			logrus.Infof("Removing autoscaling rule from the function...")
			err = utils.UpdateFunctionCustomResource(kubelessClient, &function)
			if err != nil {
				logrus.Fatal(err)
			}
			logrus.Infof("Remove Autoscaling rule from %s successfully", funcName)
		} else {
			logrus.Fatalf("Not found an autoscale definition for %s", funcName)
		}
	},
}


================================================
FILE: cmd/kubeless/autoscale/autoscaleList.go
================================================
/*
Copyright 2016 Skippbox, Ltd.
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.
*/

package autoscale

import (
	"encoding/json"
	"fmt"
	"io"

	"github.com/ghodss/yaml"
	"github.com/gosuri/uitable"
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/api/autoscaling/v2beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
)

var autoscaleListCmd = &cobra.Command{
	Use:     "list FLAG",
	Aliases: []string{"ls"},
	Short:   "list all autoscales in Kubeless",
	Long:    `list all autoscales in Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		output, err := cmd.Flags().GetString("out")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		client := utils.GetClientOutOfCluster()

		if err := doAutoscaleList(cmd.OutOrStdout(), client, ns, output); err != nil {
			logrus.Fatal(err.Error())
		}
	},
}

func init() {
	autoscaleListCmd.Flags().StringP("out", "o", "", "Output format. One of: json|yaml")
}

func doAutoscaleList(w io.Writer, client kubernetes.Interface, ns, output string) error {
	asList, err := client.AutoscalingV2beta1().HorizontalPodAutoscalers(ns).List(metav1.ListOptions{
		LabelSelector: "created-by=kubeless",
	})
	if err != nil {
		return err
	}

	return printAutoscale(w, asList.Items, output)
}

// printAutoscale formats the output of autoscale list
func printAutoscale(w io.Writer, ass []v2beta1.HorizontalPodAutoscaler, output string) error {
	if output == "" {
		table := uitable.New()
		table.MaxColWidth = 50
		table.Wrap = true
		table.AddRow("NAME", "NAMESPACE", "TARGET", "MIN", "MAX", "METRIC", "VALUE")
		for _, i := range ass {
			n := i.Name
			ns := i.Namespace
			ta := i.Spec.ScaleTargetRef.Name
			min := i.Spec.MinReplicas
			max := i.Spec.MaxReplicas
			m := ""
			v := ""
			if len(i.Spec.Metrics) == 0 {
				logrus.Errorf("The autoscale %s has bad format. It has no metric defined.", i.Name)
				continue
			}
			if i.Spec.Metrics[0].Object != nil {
				m = i.Spec.Metrics[0].Object.MetricName
				v = i.Spec.Metrics[0].Object.TargetValue.String()
			} else if i.Spec.Metrics[0].Resource != nil {
				m = string(i.Spec.Metrics[0].Resource.Name)
				v = fmt.Sprint(*i.Spec.Metrics[0].Resource.TargetAverageUtilization)
			}

			table.AddRow(n, ns, ta, fmt.Sprint(*min), fmt.Sprint(max), m, v)
		}
		fmt.Fprintln(w, table)
	} else {
		for _, i := range ass {
			switch output {
			case "json":
				b, err := json.MarshalIndent(i, "", "  ")
				if err != nil {
					return err
				}
				fmt.Fprintln(w, string(b))
			case "yaml":
				b, err := yaml.Marshal(i)
				if err != nil {
					return err
				}
				fmt.Fprintln(w, string(b))
			default:
				return fmt.Errorf("Wrong output format. Only accept json|yaml file")
			}
		}
	}
	return nil
}


================================================
FILE: cmd/kubeless/autoscale/autoscaleList_test.go
================================================
package autoscale

import (
	"bytes"
	"strings"
	"testing"

	av2alpha1 "k8s.io/api/autoscaling/v2beta1"
	"k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/fake"
)

func listAutoscaleOutput(t *testing.T, client kubernetes.Interface, ns, output string) string {
	var buf bytes.Buffer

	if err := doAutoscaleList(&buf, client, ns, output); err != nil {
		t.Fatalf("doList returned error: %v", err)
	}

	return buf.String()
}

func TestAutoscaleList(t *testing.T) {
	replicas := int32(1)
	targetAverageUtilization := int32(50)
	q, _ := resource.ParseQuantity("10k")

	as1 := av2alpha1.HorizontalPodAutoscaler{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "foo",
			Namespace: "myns",
			Labels: map[string]string{
				"created-by": "kubeless",
			},
		},
		Spec: av2alpha1.HorizontalPodAutoscalerSpec{
			ScaleTargetRef: av2alpha1.CrossVersionObjectReference{
				Kind: "Deployment",
				Name: "foo",
			},
			MinReplicas: &replicas,
			MaxReplicas: replicas,
			Metrics: []av2alpha1.MetricSpec{
				{
					Type: av2alpha1.ResourceMetricSourceType,
					Resource: &av2alpha1.ResourceMetricSource{
						Name:                     v1.ResourceCPU,
						TargetAverageUtilization: &targetAverageUtilization,
					},
				},
			},
		},
	}

	as2 := av2alpha1.HorizontalPodAutoscaler{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "bar",
			Namespace: "myns",
			Labels: map[string]string{
				"created-by": "kubeless",
			},
		},
		Spec: av2alpha1.HorizontalPodAutoscalerSpec{
			ScaleTargetRef: av2alpha1.CrossVersionObjectReference{
				Kind: "Deployment",
				Name: "foo",
			},
			MinReplicas: &replicas,
			MaxReplicas: replicas,
			Metrics: []av2alpha1.MetricSpec{
				{
					Type: av2alpha1.ObjectMetricSourceType,
					Object: &av2alpha1.ObjectMetricSource{
						MetricName:  "function_calls",
						TargetValue: q,
						Target: av2alpha1.CrossVersionObjectReference{
							Kind: "Service",
							Name: "foo",
						},
					},
				},
			},
		},
	}

	as3 := av2alpha1.HorizontalPodAutoscaler{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "foobar",
			Namespace: "myns",
		},
	}

	client := fake.NewSimpleClientset(&as1, &as2, &as3)

	output := listAutoscaleOutput(t, client, "myns", "")
	t.Log("output is", output)

	if !strings.Contains(output, "foo") || !strings.Contains(output, "bar") {
		t.Errorf("table output didn't mention both autoscales")
	}

	if strings.Contains(output, "foobar") {
		t.Errorf("table output shouldn't mention foobar autoscale as it isn't created by kubeless")
	}

	// json output
	output = listAutoscaleOutput(t, client, "myns", "json")
	t.Log("output is", output)

	// yaml output
	output = listAutoscaleOutput(t, client, "myns", "yaml")
	t.Log("output is", output)
}


================================================
FILE: cmd/kubeless/autoscale/autoscale_test.go
================================================
package autoscale

import (
	"reflect"
	"testing"

	"k8s.io/api/autoscaling/v2beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestGetHorizontalAutoscaleDefinition(t *testing.T) {
	var min, max int32
	min = 1
	max = 3
	funcName := "test-autoscale"
	ns := "default"
	value := "10"
	labels := map[string]string{
		"foo": "bar",
	}
	metric := "cpu"
	hpa, err := getHorizontalAutoscaleDefinition(funcName, ns, metric, min, max, value, labels)
	if err != nil {
		t.Fatalf("Unexpected error %v", err)
	}
	expectedMeta := metav1.ObjectMeta{
		Name:      funcName,
		Namespace: ns,
		Labels:    labels,
	}
	if hpa.Spec.ScaleTargetRef.Name != funcName {
		t.Fatalf("Creating wrong scale target name")
	}
	if !reflect.DeepEqual(expectedMeta, hpa.ObjectMeta) {
		t.Errorf("Expected \n%v to be equal to \n%v", expectedMeta, hpa.ObjectMeta)
	}
	if *hpa.Spec.MinReplicas != min {
		t.Errorf("Unexpected min replicas. Expecting %d got %d", min, *hpa.Spec.MinReplicas)
	}
	if hpa.Spec.MaxReplicas != max {
		t.Errorf("Unexpected max replicas. Expecting %d got %d", max, hpa.Spec.MaxReplicas)
	}
	if hpa.Spec.Metrics[0].Type != v2beta1.ResourceMetricSourceType ||
		*hpa.Spec.Metrics[0].Resource.TargetAverageUtilization != int32(10) {
		t.Error("Unexpected metric")
	}

	metric = "qps"
	hpa, err = getHorizontalAutoscaleDefinition(funcName, ns, metric, min, max, value, labels)
	if err != nil {
		t.Fatalf("Unexpected error %v", err)
	}
	if hpa.Spec.Metrics[0].Type != v2beta1.ObjectMetricSourceType ||
		hpa.Spec.Metrics[0].Object.TargetValue.String() != "10" {
		t.Error("Unexpected metric")
	}
}


================================================
FILE: cmd/kubeless/completion/completion.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package completion

import (
	"github.com/spf13/cobra"
	"os"
)

// CompletionCmd contains first-class command for completion
var CompletionCmd = &cobra.Command{
	Use:   "completion [bash|zsh|fish|powershell]",
	Short: "Generate completion script",
	Long: `To load completions:

Bash:

$ source <(kubeless completion bash)

# To load completions for each session, execute once:
Linux:
  $ kubeless completion bash > /etc/bash_completion.d/kubeless
MacOS:
  $ kubeless completion bash > /usr/local/etc/bash_completion.d/kubeless

Zsh:

# If shell completion is not already enabled in your environment you will need
# to enable it.  You can execute the following once:

$ echo "autoload -U compinit; compinit" >> ~/.zshrc

# To load completions for each session, execute once:
$ kubeless completion zsh > "${fpath[1]}/_kubeless"

# You will need to start a new shell for this setup to take effect.

Fish:

$ kubeless completion fish | source

# To load completions for each session, execute once:
$ kubeless completion fish > ~/.config/fish/completions/kubeless.fish
`,
	DisableFlagsInUseLine: true,
	ValidArgs:             []string{"bash", "zsh", "fish", "powershell"},
	Args:                  cobra.ExactValidArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		switch args[0] {
		case "bash":
			cmd.Root().GenBashCompletion(os.Stdout)
		case "zsh":
			cmd.Root().GenZshCompletion(os.Stdout)
		case "fish":
			cmd.Root().GenFishCompletion(os.Stdout, true)
		case "powershell":
			cmd.Root().GenPowerShellCompletion(os.Stdout)
		}
	},
}


================================================
FILE: cmd/kubeless/function/call.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/rest"
)

var callCmd = &cobra.Command{
	Use:   "call <function_name> FLAG",
	Short: "call function from cli",
	Long:  `call function from cli`,
	Run: func(cmd *cobra.Command, args []string) {
		var (
			str []byte
			get bool = false
		)

		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - function name")
		}
		funcName := args[0]

		data, err := cmd.Flags().GetString("data")
		if data == "" {
			get = true
		} else {
			str = []byte(data)
		}

		if err != nil {
			logrus.Fatal(err)
		}
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		clientset := utils.GetClientOutOfCluster()
		svc, err := clientset.CoreV1().Services(ns).Get(funcName, metav1.GetOptions{})
		if err != nil {
			logrus.Fatalf("Unable to find the service for %s", funcName)
		}

		port := strconv.Itoa(int(svc.Spec.Ports[0].Port))
		if svc.Spec.Ports[0].Name != "" {
			port = svc.Spec.Ports[0].Name
		}

		req := &rest.Request{}
		if get {
			req = clientset.CoreV1().RESTClient().Get().Namespace(ns).Resource("services").SubResource("proxy").Name(funcName + ":" + port)
		} else {
			req = clientset.CoreV1().RESTClient().Post().Namespace(ns).Resource("services").SubResource("proxy").Name(funcName + ":" + port).Body(bytes.NewBuffer(str))
			if utils.IsJSON(string(str)) {
				req.SetHeader("Content-Type", "application/json")
				req.SetHeader("event-type", "application/json")
			} else {
				req.SetHeader("Content-Type", "application/x-www-form-urlencoded")
				req.SetHeader("event-type", "application/x-www-form-urlencoded")
			}
			// REST package removes trailing slash when building URLs
			// Causing POST requests to be redirected with an empty body
			// So we need to manually build the URL
			req = req.AbsPath(req.URL().Path + "/")
		}
		timestamp := time.Now().UTC()
		eventID, err := utils.GetRandString(11)
		if err != nil {
			logrus.Fatalf("Unable to generate ID %v", err)
		}
		req.SetHeader("event-id", eventID)
		req.SetHeader("event-time", timestamp.Format(time.RFC3339))
		req.SetHeader("event-namespace", "cli.kubeless.io")
		res, err := req.Do().Raw()
		if err != nil {
			// Properly interpret line breaks
			logrus.Error(string(res))
			if strings.Contains(err.Error(), "status code 408") {
				// Give a more meaninful error for timeout errors
				logrus.Fatal("Request timeout exceeded")
			} else {
				logrus.Fatal(strings.Replace(err.Error(), `\n`, "\n", -1))
			}
		}
		fmt.Println(string(res))
	},
}

func init() {
	callCmd.Flags().StringP("data", "d", "", "Specify data for function")
	callCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")

}


================================================
FILE: cmd/kubeless/function/delete.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

var deleteCmd = &cobra.Command{
	Use:   "delete <function_name>",
	Short: "delete a function from Kubeless",
	Long:  `delete a function from Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - function name")
		}
		funcName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		kubelessClient, err := utils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatal(err)
		}

		err = utils.DeleteFunctionCustomResource(kubelessClient, funcName, ns)
		if err != nil {
			logrus.Fatal(err)
		}
	},
}

func init() {
	deleteCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
}


================================================
FILE: cmd/kubeless/function/deploy.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/ghodss/yaml"
	cronjobApi "github.com/kubeless/cronjob-trigger/pkg/apis/kubeless/v1beta1"
	cronjobUtils "github.com/kubeless/cronjob-trigger/pkg/utils"
	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	"github.com/kubeless/kubeless/pkg/langruntime"
	kubelessutil "github.com/kubeless/kubeless/pkg/utils"
	"github.com/robfig/cron"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var deployCmd = &cobra.Command{
	Use:   "deploy <function_name> FLAG",
	Short: "deploy a function to Kubeless",
	Long:  `deploy a function to Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cli := kubelessutil.GetClientOutOfCluster()
		apiExtensionsClientset := kubelessutil.GetAPIExtensionsClientOutOfCluster()

		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - function name")
		}
		funcName := args[0]

		runtime, err := cmd.Flags().GetString("runtime")
		if err != nil {
			logrus.Fatal(err)
		}

		// Checking runtime parameter if allowed by RBAC, otherwide skip the check
		config, err := kubelessutil.GetKubelessConfig(cli, apiExtensionsClientset)
		if config == nil || err != nil {
			logrus.Warnf("%v. Runtime check is disabled.", err)
		} else {
			lr := langruntime.New(config)
			lr.ReadConfigMap()

			if runtime != "" && !lr.IsValidRuntime(runtime) {
				logrus.Fatalf("Invalid runtime: %s. Supported runtimes are: %s",
					runtime, strings.Join(lr.GetRuntimes(), ", "))
			}
		}

		schedule, err := cmd.Flags().GetString("schedule")
		if err != nil {
			logrus.Fatal(err)
		}

		if schedule != "" {
			if _, err := cron.ParseStandard(schedule); err != nil {
				logrus.Fatalf("Invalid value for --schedule. " + err.Error())
			}
		}

		labels, err := cmd.Flags().GetStringSlice("label")
		if err != nil {
			logrus.Fatal(err)
		}

		envs, err := cmd.Flags().GetStringSlice("env")
		if err != nil {
			logrus.Fatal(err)
		}

		handler, err := cmd.Flags().GetString("handler")
		if err != nil {
			logrus.Fatal(err)
		}

		file, err := cmd.Flags().GetString("from-file")
		if err != nil {
			logrus.Fatal(err)
		}

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		var nsArg string
		if ns == "" {
			ns = kubelessutil.GetDefaultNamespace()
		} else {
			nsArg = fmt.Sprintf(" -n %s", ns)
		}

		deps, err := cmd.Flags().GetString("dependencies")
		if err != nil {
			logrus.Fatal(err)
		}

		secrets, err := cmd.Flags().GetStringSlice("secrets")
		if err != nil {
			logrus.Fatal(err)
		}

		serviceAccount, err := cmd.Flags().GetString("service-account")
		if err != nil {
			logrus.Fatal(err)
		}

		runtimeImage, err := cmd.Flags().GetString("runtime-image")
		if err != nil {
			logrus.Fatal(err)
		}

		imagePullPolicy, err := cmd.Flags().GetString("image-pull-policy")
		if err != nil {
			logrus.Fatal(err)
		}

		if imagePullPolicy != "IfNotPresent" && imagePullPolicy != "Always" && imagePullPolicy != "Never" {
			err := fmt.Errorf("image-pull-policy must be {IfNotPresent|Always|Never}")
			logrus.Fatal(err)
		}

		mem, err := cmd.Flags().GetString("memory")
		if err != nil {
			logrus.Fatal(err)
		}

		cpu, err := cmd.Flags().GetString("cpu")
		if err != nil {
			logrus.Fatal(err)
		}

		timeout, err := cmd.Flags().GetString("timeout")
		if err != nil {
			logrus.Fatal(err)
		}

		output, err := cmd.Flags().GetString("output")
		if err != nil {
			logrus.Fatal(err)
		}

		headless, err := cmd.Flags().GetBool("headless")
		if err != nil {
			logrus.Fatal(err)
		}

		dryrun, err := cmd.Flags().GetBool("dryrun")
		if err != nil {
			logrus.Fatal(err)
		}

		port, err := cmd.Flags().GetInt32("port")
		if err != nil {
			logrus.Fatal(err)
		}
		if port <= 0 || port > 65535 {
			logrus.Fatalf("Invalid port number %d specified", port)
		}

		servicePort, err := cmd.Flags().GetInt32("servicePort")
		if err != nil {
			logrus.Fatal(err)
		}
		if servicePort < 0 || servicePort > 65535 {
			logrus.Fatalf("Invalid servicePort number %d specified", servicePort)
		}

		funcDeps := ""
		if deps != "" {
			contentType, err := kubelessutil.GetContentType(deps)
			if err != nil {
				logrus.Fatal(err)
			}
			funcDeps, _, err = kubelessutil.ParseContent(deps, contentType)
			if err != nil {
				logrus.Fatal(err)
			}
		}

		if runtime == "" && runtimeImage == "" {
			logrus.Fatal("Either `--runtime` or `--runtime-image` flag must be specified.")
		}

		if runtime != "" && handler == "" {
			logrus.Fatal("You must specify handler for the runtime.")
		}

		nodeSelectors, err := cmd.Flags().GetStringSlice("node-selectors")
		if err != nil {
			logrus.Fatal(err)
		}

		defaultFunctionSpec := kubelessApi.Function{}
		defaultFunctionSpec.ObjectMeta.Labels = map[string]string{
			"created-by": "kubeless",
			"function":   funcName,
		}

		f, err := getFunctionDescription(funcName, ns, handler, file, funcDeps, runtime, runtimeImage, mem, cpu, timeout, imagePullPolicy, serviceAccount, port, servicePort, headless, envs, labels, secrets, nodeSelectors, defaultFunctionSpec)
		if err != nil {
			logrus.Fatal(err)
		}

		if dryrun == true {
			if output == "json" {
				j, err := json.MarshalIndent(f, "", "    ")
				if err != nil {
					logrus.Fatal(err)
				}
				fmt.Println(string(j[:]))
				return
			} else if output == "yaml" {
				y, err := yaml.Marshal(f)
				if err != nil {
					logrus.Fatal(err)
				}
				fmt.Println(string(y[:]))
				return
			} else {
				logrus.Infof("Output format needs to be yaml or json")
				return
			}
		}

		kubelessClient, err := kubelessutil.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatal(err)
		}

		logrus.Infof("Deploying function...")
		err = kubelessutil.CreateFunctionCustomResource(kubelessClient, f)
		if err != nil {
			logrus.Fatalf("Failed to deploy %s. Received:\n%s", funcName, err)
		}
		logrus.Infof("Function %s submitted for deployment", funcName)
		logrus.Infof("Check the deployment status executing 'kubeless function ls %s%s'", funcName, nsArg)

		if schedule != "" {
			cronJobTrigger := cronjobApi.CronJobTrigger{}
			cronJobTrigger.TypeMeta = metav1.TypeMeta{
				Kind:       "CronJobTrigger",
				APIVersion: "kubeless.io/v1beta1",
			}
			cronJobTrigger.ObjectMeta = metav1.ObjectMeta{
				Name:      funcName,
				Namespace: ns,
			}
			cronJobTrigger.ObjectMeta.Labels = map[string]string{
				"created-by": "kubeless",
				"function":   funcName,
			}
			cronJobTrigger.Spec.FunctionName = funcName
			cronJobTrigger.Spec.Schedule = schedule
			cronjobClient, err := cronjobUtils.GetKubelessClientOutCluster()
			if err != nil {
				logrus.Fatal(err)
			}
			err = cronjobUtils.CreateCronJobCustomResource(cronjobClient, &cronJobTrigger)
			if err != nil {
				logrus.Fatalf("Failed to deploy cron job trigger %s. Received:\n%s", funcName, err)
			}
		}
	},
}

func init() {
	deployCmd.Flags().StringP("runtime", "r", "", "Specify runtime")
	deployCmd.Flags().StringP("handler", "", "", "Specify handler")
	deployCmd.Flags().StringP("from-file", "f", "", "Specify code file or a URL to the code file")
	deployCmd.Flags().StringSliceP("label", "l", []string{}, "Specify labels of the function. Both separator ':' and '=' are allowed. For example: --label foo1=bar1,foo2:bar2")
	deployCmd.Flags().StringSliceP("secrets", "", []string{}, "Specify Secrets to be mounted to the functions container. For example: --secrets mySecret")
	deployCmd.Flags().StringSliceP("env", "e", []string{}, "Specify environment variable of the function. Both separator ':' and '=' are allowed. For example: --env foo1=bar1,foo2:bar2")
	deployCmd.Flags().StringSliceP("node-selectors", "", []string{}, "Specify node selectors for the function. Both separator ':' and '=' are allowed. For example: --node-selectors key1=val1,key2:val2")
	deployCmd.Flags().StringP("service-account", "", "", "Specify service account for the function. For example: --service-account controller-acct")
	deployCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
	deployCmd.Flags().StringP("dependencies", "d", "", "Specify a file containing list of dependencies for the function")
	deployCmd.Flags().StringP("schedule", "", "", "Specify schedule in cron format for scheduled function")
	deployCmd.Flags().StringP("memory", "", "", "Request amount of memory, which is measured in bytes, for the function. It is expressed as a plain integer or a fixed-point interger with one of these suffies: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki")
	deployCmd.Flags().StringP("cpu", "", "", "Request amount of cpu for the function, which is measured in units of cores. Please see the following link for more information: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/#meaning-of-cpu")
	deployCmd.Flags().StringP("runtime-image", "", "", "Custom runtime image")
	deployCmd.Flags().StringP("image-pull-policy", "", "Always", "Image pull policy")
	deployCmd.Flags().StringP("timeout", "", "180", "Maximum timeout (in seconds) for the function to complete its execution")
	deployCmd.Flags().StringP("output", "o", "yaml", "Output format")
	deployCmd.Flags().Bool("headless", false, "Deploy http-based function without a single service IP and load balancing support from Kubernetes. See: https://kubernetes.io/docs/concepts/services-networking/service/#headless-services")
	deployCmd.Flags().Bool("dryrun", false, "Output JSON manifest of the function without creating it")
	deployCmd.Flags().Int32("port", 8080, "Deploy http-based function with a custom port")
	deployCmd.Flags().Int32("servicePort", 0, "Deploy http-based function with a custom service port. If not provided the value of 'port' will be used")
}


================================================
FILE: cmd/kubeless/function/describe.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"encoding/json"
	"fmt"

	"github.com/ghodss/yaml"
	"github.com/gosuri/uitable"
	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

var describeCmd = &cobra.Command{
	Use:     "describe FLAG",
	Aliases: []string{"ls"},
	Short:   "describe a function deployed to Kubeless",
	Long:    `describe a function deployed to Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - function name")
		}
		funcName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatalf("Can not describe function: %v", err)
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		output, err := cmd.Flags().GetString("out")
		if err != nil {
			logrus.Fatalf("Can not describe function: %v", err)
		}

		f, err := utils.GetFunction(funcName, ns)
		if err != nil {
			logrus.Fatalf("Can not describe function: %v", err)
		}

		err = print(f, funcName, output)
		if err != nil {
			logrus.Fatalf("Can not describe function: %v", err)
		}
	},
}

func init() {
	describeCmd.Flags().StringP("out", "o", "", "Output format. One of: json|yaml")
	describeCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
}

func print(f kubelessApi.Function, name, output string) error {
	switch output {
	case "":
		table := uitable.New()
		table.MaxColWidth = 80
		table.Wrap = true
		label, err := json.Marshal(f.ObjectMeta.Labels)
		if err != nil {
			return err
		}
		var env, memory string
		if len(f.Spec.Deployment.Spec.Template.Spec.Containers) != 0 {
			b, err := json.Marshal(f.Spec.Deployment.Spec.Template.Spec.Containers[0].Env)
			if err != nil {
				return err
			}
			env = string(b)
			memory = f.Spec.Deployment.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().String()
		}

		table.AddRow("Name:", name)
		table.AddRow("Namespace:", f.ObjectMeta.Namespace)
		table.AddRow("Handler:", f.Spec.Handler)
		table.AddRow("Runtime:", f.Spec.Runtime)
		table.AddRow("Label:", string(label))
		table.AddRow("Envvar:", env)
		table.AddRow("Memory:", memory)
		table.AddRow("Dependencies:", f.Spec.Deps)
		fmt.Println(table)
	case "json":
		b, err := json.MarshalIndent(f, "", "  ")
		if err != nil {
			return err
		}
		fmt.Println(string(b))
	case "yaml":
		b, err := yaml.Marshal(f)
		if err != nil {
			return err
		}
		fmt.Println(string(b))
	default:
		fmt.Println("Wrong output format. Please use only json|yaml")
	}

	return nil
}


================================================
FILE: cmd/kubeless/function/function.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"fmt"
	"strings"

	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	"github.com/kubeless/kubeless/pkg/client/clientset/versioned"
	kubelessutil "github.com/kubeless/kubeless/pkg/utils"
	"github.com/spf13/cobra"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/client-go/kubernetes"
)

// FunctionCmd contains first-class command for function
var FunctionCmd = &cobra.Command{
	Use:   "function SUBCOMMAND",
	Short: "function specific operations",
	Long:  `function command allows user to list, deploy, edit, delete functions running on Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cmd.Help()
	},
}

func init() {
	FunctionCmd.AddCommand(deployCmd)
	FunctionCmd.AddCommand(deleteCmd)
	FunctionCmd.AddCommand(listCmd)
	FunctionCmd.AddCommand(callCmd)
	FunctionCmd.AddCommand(logsCmd)
	FunctionCmd.AddCommand(describeCmd)
	FunctionCmd.AddCommand(updateCmd)
	FunctionCmd.AddCommand(topCmd)
}

func getKV(input string) (string, string) {
	var key, value string
	if pos := strings.IndexAny(input, "=:"); pos != -1 {
		key = input[:pos]
		value = input[pos+1:]
	} else {
		// no separator found
		key = input
		value = ""
	}

	return key, value
}

func parseLabel(labels []string) map[string]string {
	funcLabels := make(map[string]string)
	for _, label := range labels {
		k, v := getKV(label)
		funcLabels[k] = v
	}
	return funcLabels
}

func parseEnv(envs []string) []v1.EnvVar {
	funcEnv := []v1.EnvVar{}
	for _, env := range envs {
		k, v := getKV(env)
		funcEnv = append(funcEnv, v1.EnvVar{
			Name:  k,
			Value: v,
		})
	}
	return funcEnv
}

func parseResource(in string) (resource.Quantity, error) {
	if in == "" {
		return resource.Quantity{}, nil
	}

	quantity, err := resource.ParseQuantity(in)
	if err != nil {
		return resource.Quantity{}, err
	}

	return quantity, nil
}

func parseNodeSelectors(nodeSelectors []string) map[string]string {
	funcNodeSelectors := make(map[string]string)
	for _, nodeSelector := range nodeSelectors {
		k, v := getKV(nodeSelector)
		funcNodeSelectors[k] = v
	}
	return funcNodeSelectors
}

func getFunctionDescription(funcName, ns, handler, file, deps, runtime, runtimeImage, mem, cpu, timeout string, imagePullPolicy string, serviceAccount string, port int32, servicePort int32, headless bool, envs, labels, secrets, nodeSelectors []string, defaultFunction kubelessApi.Function) (*kubelessApi.Function, error) {
	function := defaultFunction
	function.TypeMeta = metav1.TypeMeta{
		Kind:       "Function",
		APIVersion: "kubeless.io/v1beta1",
	}
	if handler != "" {
		function.Spec.Handler = handler
	}

	if file != "" {
		contentType, err := kubelessutil.GetContentType(file)
		if err != nil {
			return nil, err
		}
		functionContent, checksum, err := kubelessutil.ParseContent(file, contentType)
		if err != nil {
			return nil, err
		}
		if strings.Contains(contentType, "url") {
			// set the function to be the URL provided on the command line
			function.Spec.Function = file
		} else {
			function.Spec.Function = functionContent
		}
		function.Spec.Checksum = checksum
		function.Spec.FunctionContentType = contentType
	}

	if deps != "" {
		function.Spec.Deps = deps
	}

	if runtime != "" {
		function.Spec.Runtime = runtime
	}

	if timeout != "" {
		function.Spec.Timeout = timeout
	}

	funcEnv := parseEnv(envs)
	if len(funcEnv) == 0 && len(defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers) != 0 {
		funcEnv = defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers[0].Env
	}

	funcLabels := defaultFunction.ObjectMeta.Labels
	if len(funcLabels) == 0 {
		funcLabels = make(map[string]string)
	}
	ls := parseLabel(labels)
	for k, v := range ls {
		funcLabels[k] = v
	}
	function.ObjectMeta = metav1.ObjectMeta{
		Name:      funcName,
		Namespace: ns,
		Labels:    funcLabels,
	}

	resources := v1.ResourceRequirements{}
	if mem != "" || cpu != "" {
		funcMem, err := parseResource(mem)
		if err != nil {
			err = fmt.Errorf("Wrong format of the memory value: %v", err)
			return &kubelessApi.Function{}, err
		}
		funcCPU, err := parseResource(cpu)
		if err != nil {
			err = fmt.Errorf("Wrong format for cpu value: %v", err)
			return &kubelessApi.Function{}, err
		}
		resource := map[v1.ResourceName]resource.Quantity{
			v1.ResourceMemory: funcMem,
			v1.ResourceCPU:    funcCPU,
		}

		resources = v1.ResourceRequirements{
			Limits:   resource,
			Requests: resource,
		}
	} else {
		if len(defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers) != 0 {
			resources = defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers[0].Resources
		}
	}

	if len(runtimeImage) == 0 && len(defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers) != 0 {
		runtimeImage = defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers[0].Image
	}
	function.Spec.Deployment.Spec.Template.Spec.Containers = []v1.Container{
		{
			ImagePullPolicy: v1.PullPolicy(imagePullPolicy),
			Env:             funcEnv,
			Resources:       resources,
			Image:           runtimeImage,
		},
	}

	if serviceAccount != "" {
		function.Spec.Deployment.Spec.Template.Spec.ServiceAccountName = serviceAccount
	}

	if len(defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers) != 0 {
		function.Spec.Deployment.Spec.Template.Spec.Containers[0].VolumeMounts = defaultFunction.Spec.Deployment.Spec.Template.Spec.Containers[0].VolumeMounts
	}

	svcSpec := v1.ServiceSpec{
		Ports: []v1.ServicePort{
			{
				Name:     "http-function-port",
				NodePort: 0,
				Protocol: v1.ProtocolTCP,
			},
		},
		Selector: funcLabels,
		Type:     v1.ServiceTypeClusterIP,
	}

	if headless {
		svcSpec.ClusterIP = v1.ClusterIPNone
	}

	if port != 0 {
		svcSpec.Ports[0].Port = port
		svcSpec.Ports[0].TargetPort = intstr.FromInt(int(port))
	}
	if servicePort != 0 {
		svcSpec.Ports[0].Port = servicePort
	}
	function.Spec.ServiceSpec = svcSpec

	for _, secret := range secrets {
		function.Spec.Deployment.Spec.Template.Spec.Volumes = append(function.Spec.Deployment.Spec.Template.Spec.Volumes, v1.Volume{
			Name: secret + "-vol",
			VolumeSource: v1.VolumeSource{
				Secret: &v1.SecretVolumeSource{
					SecretName: secret,
				},
			},
		})
		function.Spec.Deployment.Spec.Template.Spec.Containers[0].VolumeMounts = append(function.Spec.Deployment.Spec.Template.Spec.Containers[0].VolumeMounts, v1.VolumeMount{
			Name:      secret + "-vol",
			MountPath: "/" + secret,
		})

	}

	funcNodeSelectors := parseNodeSelectors(nodeSelectors)
	if len(funcNodeSelectors) == 0 && len(defaultFunction.Spec.Deployment.Spec.Template.Spec.NodeSelector) != 0 {
		funcNodeSelectors = defaultFunction.Spec.Deployment.Spec.Template.Spec.NodeSelector
	}
	function.Spec.Deployment.Spec.Template.Spec.NodeSelector = funcNodeSelectors

	return &function, nil
}

func getDeploymentStatus(cli kubernetes.Interface, funcName, ns string) (string, error) {
	dpm, err := cli.AppsV1().Deployments(ns).Get(funcName, metav1.GetOptions{})
	if err != nil {
		return "", err
	}
	status := fmt.Sprintf("%d/%d", dpm.Status.ReadyReplicas, dpm.Status.Replicas)
	if dpm.Status.ReadyReplicas > 0 {
		status += " READY"
	} else {
		status += " NOT READY"
	}
	return status, nil
}

func getFunctions(kubelessClient versioned.Interface, namespace, functionName string) ([]*kubelessApi.Function, error) {
	if functionName == "" {
		f, err := kubelessClient.KubelessV1beta1().Functions(namespace).List(metav1.ListOptions{})
		if err != nil {
			return []*kubelessApi.Function{}, err
		}
		return f.Items, nil
	}

	f, err := kubelessClient.KubelessV1beta1().Functions(namespace).Get(functionName, metav1.GetOptions{})
	if err != nil {
		return []*kubelessApi.Function{}, err
	}
	return []*kubelessApi.Function{
		f,
	}, nil
}


================================================
FILE: cmd/kubeless/function/function_test.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"archive/tar"
	"archive/zip"
	"compress/gzip"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"os"
	"reflect"
	"testing"

	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	appsv1 "k8s.io/api/apps/v1"
	"k8s.io/api/autoscaling/v2beta1"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
)

func TestParseLabel(t *testing.T) {
	labels := []string{
		"foo=bar",
		"bar:foo",
		"foobar",
	}
	expected := map[string]string{
		"foo":    "bar",
		"bar":    "foo",
		"foobar": "",
	}
	actual := parseLabel(labels)
	if eq := reflect.DeepEqual(expected, actual); !eq {
		t.Errorf("Expect %v got %v", expected, actual)
	}
}

func TestParseEnv(t *testing.T) {
	envs := []string{
		"foo=bar",
		"bar:foo",
		"foobar",
		"foo=bar=baz",
		"qux=bar,baz",
	}
	expected := []v1.EnvVar{
		{
			Name:  "foo",
			Value: "bar",
		},
		{
			Name:  "bar",
			Value: "foo",
		},
		{
			Name:  "foobar",
			Value: "",
		},
		{
			Name:  "foo",
			Value: "bar=baz",
		},
		{
			Name:  "qux",
			Value: "bar,baz",
		},
	}
	actual := parseEnv(envs)
	if eq := reflect.DeepEqual(expected, actual); !eq {
		t.Errorf("Expect %v got %v", expected, actual)
	}
}

func TestParseNodeSelectors(t *testing.T) {
	nodeSelectors := []string{
		"foo=bar",
		"baz:qux",
	}
	expected := map[string]string{
		"foo": "bar",
		"baz": "qux",
	}
	actual := parseNodeSelectors(nodeSelectors)
	if eq := reflect.DeepEqual(expected, actual); !eq {
		t.Errorf("Expect %v got %v", expected, actual)
	}
}

func TestGetFunctionDescription(t *testing.T) {
	// It should parse the given values
	file, err := ioutil.TempFile("", "test")
	if err != nil {
		t.Error(err)
	}
	_, err = file.WriteString("function")
	if err != nil {
		t.Error(err)
	}
	file.Close()
	defer os.Remove(file.Name()) // clean up

	result, err := getFunctionDescription("test", "default", "file.handler", file.Name(), "dependencies", "runtime", "test-image", "128Mi", "", "10", "Always", "serviceAccount", 8080, 0, false, []string{"TEST=1"}, []string{"test=1"}, []string{"secretName"}, []string{"foo1=bar1", "baz1:qux1"}, kubelessApi.Function{})

	if err != nil {
		t.Error(err)
	}
	parsedMem, _ := parseResource("128Mi")
	parsedCPU, _ := parseResource("")
	expectedFunction := kubelessApi.Function{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Function",
			APIVersion: "kubeless.io/v1beta1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      "test",
			Namespace: "default",
			Labels: map[string]string{
				"test": "1",
			},
		},
		Spec: kubelessApi.FunctionSpec{
			Handler:             "file.handler",
			Runtime:             "runtime",
			Function:            "function",
			Checksum:            "sha256:78f9ac018e554365069108352dacabb7fbd15246edf19400677e3b54fe24e126",
			FunctionContentType: "text",
			Deps:                "dependencies",
			Timeout:             "10",
			Deployment: appsv1.Deployment{
				Spec: appsv1.DeploymentSpec{
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							ServiceAccountName: "serviceAccount",
							Containers: []v1.Container{
								{
									Env: []v1.EnvVar{{
										Name:  "TEST",
										Value: "1",
									}},
									Resources: v1.ResourceRequirements{
										Limits: map[v1.ResourceName]resource.Quantity{
											v1.ResourceMemory: parsedMem,
											v1.ResourceCPU:    parsedCPU,
										},
										Requests: map[v1.ResourceName]resource.Quantity{
											v1.ResourceMemory: parsedMem,
											v1.ResourceCPU:    parsedCPU,
										},
									},
									Image:           "test-image",
									ImagePullPolicy: v1.PullAlways,
									VolumeMounts: []v1.VolumeMount{
										{
											Name:      "secretName-vol",
											MountPath: "/secretName",
										},
									},
								},
							},
							Volumes: []v1.Volume{
								{
									Name: "secretName-vol",
									VolumeSource: v1.VolumeSource{
										Secret: &v1.SecretVolumeSource{
											SecretName: "secretName",
										},
									},
								},
							},
							NodeSelector: map[string]string{
								"foo1": "bar1",
								"baz1": "qux1",
							},
						},
					},
				},
			},
			ServiceSpec: v1.ServiceSpec{
				Ports: []v1.ServicePort{
					{Name: "http-function-port", Protocol: "TCP", Port: 8080, TargetPort: intstr.FromInt(8080)},
				},
				Selector: map[string]string{
					"test": "1",
				},
				Type: v1.ServiceTypeClusterIP,
			},
		},
	}
	if !reflect.DeepEqual(expectedFunction, *result) {
		t.Errorf("Unexpected result. Expecting:\n %+v\nReceived:\n %+v", expectedFunction, *result)
	}

	// It should take the default values
	result2, err := getFunctionDescription("test", "default", "", "", "", "", "", "", "", "", "Always", "", 8080, 0, false, []string{}, []string{}, []string{}, []string{}, expectedFunction)

	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(expectedFunction, *result2) {
		t.Errorf("Unexpected result. Expecting:\n %+v\n Received %+v\n", expectedFunction, *result2)
	}

	// Given parameters should take precedence from default values
	file, err = ioutil.TempFile("", "test")
	if err != nil {
		t.Error(err)
	}
	_, err = file.WriteString("function-modified")
	if err != nil {
		t.Error(err)
	}
	file.Close()
	defer os.Remove(file.Name()) // clean up

	result3, err := getFunctionDescription("test", "default", "file.handler2", file.Name(), "dependencies2", "runtime2", "test-image2", "256Mi", "100m", "20", "Always", "NewServiceAccount", 8080, 0, false, []string{"TEST=2"}, []string{"test=2"}, []string{"secret2"}, []string{"foo2=bar2", "baz2:qux2"}, expectedFunction)

	if err != nil {
		t.Error(err)
	}
	parsedMem2, _ := parseResource("256Mi")
	parsedCPU2, _ := parseResource("100m")
	newFunction := kubelessApi.Function{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Function",
			APIVersion: "kubeless.io/v1beta1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      "test",
			Namespace: "default",
			Labels: map[string]string{
				"test": "2",
			},
		},
		Spec: kubelessApi.FunctionSpec{
			Handler:             "file.handler2",
			Runtime:             "runtime2",
			Function:            "function-modified",
			FunctionContentType: "text",
			Checksum:            "sha256:1958eb96d7d3cadedd0f327f09322eb7db296afb282ed91aa66cb4ab0dcc3c9f",
			Deps:                "dependencies2",
			Timeout:             "20",
			Deployment: appsv1.Deployment{
				Spec: appsv1.DeploymentSpec{
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							ServiceAccountName: "NewServiceAccount",
							Containers: []v1.Container{
								{
									Env: []v1.EnvVar{{
										Name:  "TEST",
										Value: "2",
									}},
									Resources: v1.ResourceRequirements{
										Limits: map[v1.ResourceName]resource.Quantity{
											v1.ResourceMemory: parsedMem2,
											v1.ResourceCPU:    parsedCPU2,
										},
										Requests: map[v1.ResourceName]resource.Quantity{
											v1.ResourceMemory: parsedMem2,
											v1.ResourceCPU:    parsedCPU2,
										},
									},
									Image:           "test-image2",
									ImagePullPolicy: v1.PullAlways,
									VolumeMounts: []v1.VolumeMount{
										{
											Name:      "secretName-vol",
											MountPath: "/secretName",
										}, {
											Name:      "secret2-vol",
											MountPath: "/secret2",
										},
									},
								},
							},
							Volumes: []v1.Volume{
								{
									Name: "secretName-vol",
									VolumeSource: v1.VolumeSource{
										Secret: &v1.SecretVolumeSource{
											SecretName: "secretName",
										},
									},
								}, {
									Name: "secret2-vol",
									VolumeSource: v1.VolumeSource{
										Secret: &v1.SecretVolumeSource{
											SecretName: "secret2",
										},
									},
								},
							},
							NodeSelector: map[string]string{
								"foo2": "bar2",
								"baz2": "qux2",
							},
						},
					},
				},
			},
			ServiceSpec: v1.ServiceSpec{
				Ports: []v1.ServicePort{
					{Name: "http-function-port", Protocol: "TCP", Port: 8080, TargetPort: intstr.FromInt(8080)},
				},
				Selector: map[string]string{
					"test": "2",
				},
				Type: v1.ServiceTypeClusterIP,
			},
		},
	}
	if !reflect.DeepEqual(newFunction, *result3) {
		t.Errorf("Unexpected result. Expecting:\n %+v\n Received %+v\n", newFunction, *result3)
	}

	// It should detect that it is a Zip file or a compressed tar file
	file, err = os.Open(file.Name())
	if err != nil {
		t.Error(err)
	}

	zipFile, err := os.Create(file.Name() + ".zip")
	if err != nil {
		t.Error(err)
	}
	defer os.Remove(zipFile.Name()) // clean up

	tarGzFile, err := os.Create(file.Name() + ".tar.gz")
	if err != nil {
		t.Error(err)
	}
	defer os.Remove(tarGzFile.Name()) // clean up

	zipW := zip.NewWriter(zipFile)
	gzipW := gzip.NewWriter(tarGzFile)
	tarW := tar.NewWriter(gzipW)

	info, err := file.Stat()
	if err != nil {
		t.Error(err)
	}

	zipHeader, err := zip.FileInfoHeader(info)
	if err != nil {
		t.Error(err)
	}
	writer, err := zipW.CreateHeader(zipHeader)
	if err != nil {
		t.Error(err)
	}
	_, err = io.Copy(writer, file)
	if err != nil {
		t.Error(err)
	}

	tarHeader, err := tar.FileInfoHeader(info, info.Name())
	if err != nil {
		t.Error(err)
	}
	tarHeader.Name = file.Name()
	err = tarW.WriteHeader(tarHeader)
	if err != nil {
		t.Error(err)
	}
	_, err = io.Copy(writer, file)
	if err != nil {
		t.Error(err)
	}

	file.Close()
	zipW.Close()
	zipFile.Close()
	tarW.Close()
	gzipW.Close()
	tarGzFile.Close()

	result4A, err := getFunctionDescription("test", "default", "file.handler", zipFile.Name(), "dependencies", "runtime", "", "", "", "", "Always", "", 8080, 0, false, []string{}, []string{}, []string{}, []string{}, expectedFunction)
	if err != nil {
		t.Error(err)
	}
	if result4A.Spec.FunctionContentType != "base64+zip" {
		t.Errorf("Should return base64+zip, received %s", result4A.Spec.FunctionContentType)
	}

	result4B, err := getFunctionDescription("test", "default", "file.handler", tarGzFile.Name(), "dependencies", "runtime", "", "", "", "", "Always", "", 8080, 0, false, []string{}, []string{}, []string{}, []string{}, expectedFunction)
	if err != nil {
		t.Error(err)
	}
	if result4B.Spec.FunctionContentType != "base64+compressedtar" {
		t.Errorf("Should return base64+compressedtar, received %s", result4B.Spec.FunctionContentType)
	}

	// It should maintain previous HPA definition
	result5, err := getFunctionDescription("test", "default", "file.handler", file.Name(), "dependencies", "runtime", "test-image", "128Mi", "", "10", "Always", "serviceAccount", 8080, 0, false, []string{"TEST=1"}, []string{"test=1"}, []string{}, []string{}, kubelessApi.Function{

		Spec: kubelessApi.FunctionSpec{
			HorizontalPodAutoscaler: v2beta1.HorizontalPodAutoscaler{
				ObjectMeta: metav1.ObjectMeta{
					Name: "previous-hpa",
				},
			},
		},
	})
	if result5.Spec.HorizontalPodAutoscaler.ObjectMeta.Name != "previous-hpa" {
		t.Error("should maintain previous HPA definition")
	}

	// It should set the Port, ServicePort and headless service properly
	result6, err := getFunctionDescription("test", "default", "file.handler", file.Name(), "dependencies", "runtime", "test-image", "128Mi", "", "", "Always", "serviceAccount", 9091, 9092, true, []string{}, []string{}, []string{}, []string{}, kubelessApi.Function{})
	expectedPort := v1.ServicePort{
		Name:       "http-function-port",
		Port:       9092,
		TargetPort: intstr.FromInt(9091),
		NodePort:   0,
		Protocol:   v1.ProtocolTCP,
	}
	if !reflect.DeepEqual(result6.Spec.ServiceSpec.Ports[0], expectedPort) {
		t.Errorf("Unexpected port definition: %v", result6.Spec.ServiceSpec.Ports[0])
	}
	if result6.Spec.ServiceSpec.ClusterIP != v1.ClusterIPNone {
		t.Errorf("Unexpected clusterIP %v", result6.Spec.ServiceSpec.ClusterIP)
	}

	// it should create a function from a URL
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "function")
	}))
	defer ts.Close()

	expectedURLFunction := kubelessApi.Function{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Function",
			APIVersion: "kubeless.io/v1beta1",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      "test",
			Namespace: "default",
			Labels: map[string]string{
				"test": "1",
			},
		},
		Spec: kubelessApi.FunctionSpec{
			Handler:             "file.handler",
			Runtime:             "runtime",
			Function:            ts.URL,
			Checksum:            "sha256:78f9ac018e554365069108352dacabb7fbd15246edf19400677e3b54fe24e126",
			FunctionContentType: "url",
			Deps:                "dependencies",
			Timeout:             "10",
			Deployment: appsv1.Deployment{
				Spec: appsv1.DeploymentSpec{
					Template: v1.PodTemplateSpec{
						Spec: v1.PodSpec{
							ServiceAccountName: "serviceAccount",
							Containers: []v1.Container{
								{
									Env: []v1.EnvVar{{
										Name:  "TEST",
										Value: "1",
									}},
									Resources: v1.ResourceRequirements{
										Limits: map[v1.ResourceName]resource.Quantity{
											v1.ResourceMemory: parsedMem,
											v1.ResourceCPU:    parsedCPU,
										},
										Requests: map[v1.ResourceName]resource.Quantity{
											v1.ResourceMemory: parsedMem,
											v1.ResourceCPU:    parsedCPU,
										},
									},
									Image:           "test-image",
									ImagePullPolicy: v1.PullAlways,
									VolumeMounts: []v1.VolumeMount{
										{
											Name:      "secretName-vol",
											MountPath: "/secretName",
										},
									},
								},
							},
							Volumes: []v1.Volume{
								{
									Name: "secretName-vol",
									VolumeSource: v1.VolumeSource{
										Secret: &v1.SecretVolumeSource{
											SecretName: "secretName",
										},
									},
								},
							},
							NodeSelector: map[string]string{
								"foo3": "bar3",
								"baz3": "qux3",
							},
						},
					},
				},
			},
			ServiceSpec: v1.ServiceSpec{
				Ports: []v1.ServicePort{
					{Name: "http-function-port", Protocol: "TCP", Port: 8080, TargetPort: intstr.FromInt(8080)},
				},
				Selector: map[string]string{
					"test": "1",
				},
				Type: v1.ServiceTypeClusterIP,
			},
		},
	}

	result7, err := getFunctionDescription("test", "default", "file.handler", ts.URL, "dependencies", "runtime", "test-image", "128Mi", "", "10", "Always", "serviceAccount", 8080, 0, false, []string{"TEST=1"}, []string{"test=1"}, []string{"secretName"}, []string{"foo3=bar3", "baz3:qux3"}, kubelessApi.Function{})

	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(expectedURLFunction, *result7) {
		t.Errorf("Unexpected result. Expecting:\n %+v\nReceived:\n %+v", expectedURLFunction, *result7)
	}

	// It should handle zip files and compressed tar files from a URL and detect url+zip and url+compressedtar encoding respectively
	zipBytes, err := ioutil.ReadFile(zipFile.Name())
	if err != nil {
		t.Error(err)
	}

	ts2A := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write(zipBytes)
	}))
	defer ts2A.Close()

	expectedURLFunction.Spec.FunctionContentType = "url+zip"
	expectedURLFunction.Spec.Function = ts2A.URL + "/test.zip"
	expectedURLFunction.Spec.Checksum, err = getSha256(zipBytes)
	if err != nil {
		t.Error(err)
	}

	result8A, err := getFunctionDescription("test", "default", "file.handler", ts2A.URL+"/test.zip", "dependencies", "runtime", "test-image", "128Mi", "", "10", "Always", "serviceAccount", 8080, 0, false, []string{"TEST=1"}, []string{"test=1"}, []string{"secretName"}, []string{"foo3=bar3", "baz3:qux3"}, kubelessApi.Function{})
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(expectedURLFunction, *result8A) {
		t.Errorf("Unexpected result. Expecting:\n %+v\nReceived:\n %+v", expectedURLFunction, *result8A)
	}

	tarGzBytes, err := ioutil.ReadFile(tarGzFile.Name())
	if err != nil {
		t.Error(err)
	}
	ts2B := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Write(tarGzBytes)
	}))
	defer ts2B.Close()

	expectedURLFunction.Spec.FunctionContentType = "url+compressedtar"
	expectedURLFunction.Spec.Function = ts2B.URL + "/test.tar.gz"
	expectedURLFunction.Spec.Checksum, err = getSha256(tarGzBytes)
	if err != nil {
		t.Error(err)
	}

	result8B, err := getFunctionDescription("test", "default", "file.handler", ts2B.URL+"/test.tar.gz", "dependencies", "runtime", "test-image", "128Mi", "", "10", "Always", "serviceAccount", 8080, 0, false, []string{"TEST=1"}, []string{"test=1"}, []string{"secretName"}, []string{"foo3=bar3", "baz3:qux3"}, kubelessApi.Function{})
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(expectedURLFunction, *result8B) {
		t.Errorf("Unexpected result. Expecting:\n %+v\nReceived:\n %+v", expectedURLFunction, *result8B)
	}
	// end test
}

func getSha256(bytes []byte) (string, error) {
	h := sha256.New()
	_, err := h.Write(bytes)
	if err != nil {
		return "", err
	}
	checksum := hex.EncodeToString(h.Sum(nil))
	return "sha256:" + checksum, nil
}


================================================
FILE: cmd/kubeless/function/list.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"strings"

	"github.com/ghodss/yaml"
	"github.com/gosuri/uitable"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	k8sErrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"

	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	"github.com/kubeless/kubeless/pkg/client/clientset/versioned"
	"github.com/kubeless/kubeless/pkg/utils"
)

var listCmd = &cobra.Command{
	Use:     "list FLAG",
	Aliases: []string{"ls"},
	Short:   "list all functions deployed to Kubeless",
	Long:    `list all functions deployed to Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		output, err := cmd.Flags().GetString("out")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		kubelessClient, err := utils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not list functions: %v", err)
		}

		apiV1Client := utils.GetClientOutOfCluster()

		if err := doList(cmd.OutOrStdout(), kubelessClient, apiV1Client, ns, output, args); err != nil {
			logrus.Fatal(err.Error())
		}
	},
}

func init() {
	listCmd.Flags().StringP("out", "o", "", "Output format. One of: json|yaml")
	listCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
}

func doList(w io.Writer, kubelessClient versioned.Interface, apiV1Client kubernetes.Interface, ns, output string, args []string) error {
	var list []*kubelessApi.Function
	if len(args) == 0 {
		funcList, err := kubelessClient.KubelessV1beta1().Functions(ns).List(metav1.ListOptions{})
		if err != nil {
			return err
		}
		list = funcList.Items
	} else {
		list = make([]*kubelessApi.Function, 0, len(args))
		for _, arg := range args {
			f, err := kubelessClient.KubelessV1beta1().Functions(ns).Get(arg, metav1.GetOptions{})
			if err != nil {
				return fmt.Errorf("Error listing function %s: %v", arg, err)
			}
			list = append(list, f)
		}
	}

	return printFunctions(w, list, apiV1Client, output)
}

func parseDeps(deps, runtime string) (res string, err error) {
	if deps != "" {
		if strings.Contains(runtime, "nodejs") {
			pkgjson := make(map[string]interface{})
			err = json.Unmarshal([]byte(deps), &pkgjson)
			if err != nil {
				return
			}
			if pkgjson["dependencies"] != nil {
				dependencies := []string{}
				for pkg, ver := range pkgjson["dependencies"].(map[string]interface{}) {
					dependencies = append(dependencies, pkg+": "+ver.(string))
				}
				res = strings.Join(dependencies, "\n")
			}
		} else {
			res = deps
		}
	}
	return
}

// printFunctions formats the output of function list
func printFunctions(w io.Writer, functions []*kubelessApi.Function, cli kubernetes.Interface, output string) error {
	if output == "" {
		table := uitable.New()
		table.MaxColWidth = 50
		table.Wrap = true
		table.AddRow("NAME", "NAMESPACE", "HANDLER", "RUNTIME", "DEPENDENCIES", "STATUS")
		for _, f := range functions {
			n := f.ObjectMeta.Name
			h := f.Spec.Handler
			r := f.Spec.Runtime
			ns := f.ObjectMeta.Namespace
			status, err := getDeploymentStatus(cli, f.ObjectMeta.Name, f.ObjectMeta.Namespace)
			if err != nil && k8sErrors.IsNotFound(err) {
				status = "MISSING: Check controller logs"
			} else if err != nil {
				return err
			}
			deps, err := parseDeps(f.Spec.Deps, r)
			if err != nil {
				return err
			}
			table.AddRow(n, ns, h, r, deps, status)
		}
		fmt.Fprintln(w, table)
	} else if output == "wide" {
		table := uitable.New()
		table.MaxColWidth = 50
		table.Wrap = true
		table.AddRow("NAME", "NAMESPACE", "HANDLER", "RUNTIME", "TYPE", "TOPIC", "DEPENDENCIES", "STATUS", "MEMORY", "ENV", "LABEL", "SCHEDULE")
		for _, f := range functions {
			n := f.ObjectMeta.Name
			h := f.Spec.Handler
			r := f.Spec.Runtime
			deps, err := parseDeps(f.Spec.Deps, r)
			if err != nil {
				return err
			}
			ns := f.ObjectMeta.Namespace
			status, err := getDeploymentStatus(cli, f.ObjectMeta.Name, f.ObjectMeta.Namespace)
			if err != nil && k8sErrors.IsNotFound(err) {
				status = "MISSING: Check controller logs"
			} else if err != nil {
				return err
			}
			mem := ""
			env := ""
			if len(f.Spec.Deployment.Spec.Template.Spec.Containers[0].Resources.Requests) != 0 {
				mem = f.Spec.Deployment.Spec.Template.Spec.Containers[0].Resources.Requests.Memory().String()
			}
			if len(f.Spec.Deployment.Spec.Template.Spec.Containers[0].Env) != 0 {
				var buffer bytes.Buffer
				for _, e := range f.Spec.Deployment.Spec.Template.Spec.Containers[0].Env {
					buffer.WriteString(e.Name + " = " + e.Value + "\n")
				}
				env = buffer.String()
			}
			label := ""
			if len(f.ObjectMeta.Labels) > 0 {
				var buffer bytes.Buffer
				for k, v := range f.ObjectMeta.Labels {
					buffer.WriteString(k + " : " + v + "\n")
				}
				label = buffer.String()
			}
			table.AddRow(n, ns, h, r, deps, status, mem, env, label)
		}
		fmt.Fprintln(w, table)
	} else {
		switch output {
		case "json":
			b, err := json.MarshalIndent(functions, "", "  ")
			if err != nil {
				return err
			}
			fmt.Fprintln(w, string(b))
		case "yaml":
			b, err := yaml.Marshal(functions)
			if err != nil {
				return err
			}
			fmt.Fprintln(w, string(b))
		default:
			return fmt.Errorf("Wrong output format. Please use only json|yaml")
		}
	}
	return nil
}


================================================
FILE: cmd/kubeless/function/list_test.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"bytes"
	"regexp"
	"strings"
	"testing"

	appsv1 "k8s.io/api/apps/v1"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/fake"

	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	"github.com/kubeless/kubeless/pkg/client/clientset/versioned"
	fFake "github.com/kubeless/kubeless/pkg/client/clientset/versioned/fake"
)

func listOutput(t *testing.T, client versioned.Interface, apiV1Client kubernetes.Interface, ns, output string, args []string) string {
	var buf bytes.Buffer

	if err := doList(&buf, client, apiV1Client, ns, output, args); err != nil {
		t.Fatalf("doList returned error: %v", err)
	}

	return buf.String()
}

func TestList(t *testing.T) {
	funcMem, _ := parseResource("128Mi")
	listObj := kubelessApi.FunctionList{
		Items: []*kubelessApi.Function{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "foo",
					Namespace: "myns",
				},
				Spec: kubelessApi.FunctionSpec{
					Handler:  "fhandler",
					Function: "ffunction",
					Runtime:  "fruntime",
					Deps:     "fdeps",
					Deployment: appsv1.Deployment{
						Spec: appsv1.DeploymentSpec{
							Template: v1.PodTemplateSpec{
								Spec: v1.PodSpec{
									Containers: []v1.Container{{}},
								},
							},
						},
					},
				},
			},
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "bar",
					Namespace: "myns",
					Labels: map[string]string{
						"foo": "bar",
					},
				},
				Spec: kubelessApi.FunctionSpec{
					Handler:  "bhandler",
					Function: "bfunction",
					Runtime:  "nodejs6",
					Deps:     "{\"dependencies\": {\"test\": \"^1.0.0\"}}",
					Deployment: appsv1.Deployment{
						Spec: appsv1.DeploymentSpec{
							Template: v1.PodTemplateSpec{
								Spec: v1.PodSpec{
									Containers: []v1.Container{
										{
											Env: []v1.EnvVar{
												{
													Name:  "foo",
													Value: "bar",
												},
												{
													Name:  "foo2",
													Value: "bar2",
												},
											},
											Resources: v1.ResourceRequirements{
												Limits: map[v1.ResourceName]resource.Quantity{
													v1.ResourceMemory: funcMem,
												},
												Requests: map[v1.ResourceName]resource.Quantity{
													v1.ResourceMemory: funcMem,
												},
											},
										},
									},
								},
							},
						},
					},
				},
			},
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "wrong",
					Namespace: "myns",
				},
				Spec: kubelessApi.FunctionSpec{
					Handler:  "fhandler",
					Function: "ffunction",
					Runtime:  "fruntime",
					Deps:     "fdeps",
					Deployment: appsv1.Deployment{
						Spec: appsv1.DeploymentSpec{
							Template: v1.PodTemplateSpec{
								Spec: v1.PodSpec{
									Containers: []v1.Container{{}},
								},
							},
						},
					},
				},
			},
		},
	}

	client := fFake.NewSimpleClientset(listObj.Items[0], listObj.Items[1], listObj.Items[2])

	deploymentFoo := appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "foo",
			Namespace: "myns",
		},
		Status: appsv1.DeploymentStatus{
			Replicas:      int32(1),
			ReadyReplicas: int32(1),
		},
	}
	deploymentBar := appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "bar",
			Namespace: "myns",
		},
		Status: appsv1.DeploymentStatus{
			Replicas:      int32(2),
			ReadyReplicas: int32(0),
		},
	}
	apiV1Client := fake.NewSimpleClientset(&deploymentFoo, &deploymentBar)

	// No arg -> list everything in namespace
	output := listOutput(t, client, apiV1Client, "myns", "", []string{})
	t.Log("output is", output)

	if !strings.Contains(output, "foo") || !strings.Contains(output, "bar") {
		t.Errorf("table output didn't mention both functions")
	}
	// Status
	m, err := regexp.MatchString("foo.*1/1 READY", output)
	if err != nil {
		t.Fatal(err)
	}
	if !m {
		t.Errorf("table output didn't mention deployment status")
	}
	m, err = regexp.MatchString("bar.*0/2 NOT READY", output)
	if err != nil {
		t.Fatal(err)
	}
	if !m {
		t.Errorf("table output didn't mention deployment status")
	}
	m, err = regexp.MatchString("wrong.*MISSING", output)
	if err != nil {
		t.Fatal(err)
	}
	if !m {
		t.Errorf("table output didn't mention deployment status")
	}

	// Explicit arg(s)
	output = listOutput(t, client, apiV1Client, "myns", "", []string{"foo"})
	t.Log("output is", output)

	if !strings.Contains(output, "foo") {
		t.Errorf("table output didn't mention explicit function foo")
	}
	if strings.Contains(output, "bar") {
		t.Errorf("table output mentions unrequested function bar")
	}

	if strings.Contains(output, "test: ^1.0.0") {
		t.Errorf("table output doesn't show parsed dependencies")
	}

	// TODO: Actually validate the output of the following.
	// Probably need to fix output framing first.

	// json output
	output = listOutput(t, client, apiV1Client, "myns", "json", []string{})
	t.Log("output is", output)
	if !strings.Contains(output, "foo") || !strings.Contains(output, "bar") {
		t.Errorf("table output didn't mention both functions")
	}

	// yaml output
	output = listOutput(t, client, apiV1Client, "myns", "yaml", []string{})
	t.Log("output is", output)
	if !strings.Contains(output, "128Mi") {
		t.Errorf("table output didn't mention proper memory of function")
	}

	// wide output
	output = listOutput(t, client, apiV1Client, "myns", "wide", []string{})
	t.Log("output is", output)
	if !strings.Contains(output, "foo = bar") {
		t.Errorf("table output didn't mention proper env of function")
	}
}


================================================
FILE: cmd/kubeless/function/logs.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"io"
	"os"

	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/api/core/v1"
)

var logsCmd = &cobra.Command{
	Use:   "logs <function_name> FLAG",
	Short: "get logs from a running function",
	Long:  `get logs from a running function`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - function name")
		}
		funcName := args[0]
		follow, err := cmd.Flags().GetBool("follow")
		if err != nil {
			logrus.Fatal(err)
		}
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}

		k8sClient := utils.GetClientOutOfCluster()
		if err != nil {
			logrus.Fatalf("Getting log failed: %v", err)
		}
		pods, err := utils.GetPodsByLabel(k8sClient, ns, "function", funcName)
		if err != nil {
			logrus.Fatalf("Can't find the function pod: %v", err)
		}
		readyPod, err := utils.GetReadyPod(pods)
		if err != nil {
			logrus.Fatalf("No function pod is running: %v", err)
		}
		podLog := &v1.PodLogOptions{
			Container: funcName,
			Follow:    follow,
		}
		req := k8sClient.Core().Pods(ns).GetLogs(readyPod.Name, podLog)

		readCloser, err := req.Stream()
		if err != nil {
			logrus.Fatalf("Getting log failed: %v", err)
		}
		defer readCloser.Close()
		io.Copy(os.Stdout, readCloser)
	},
}

func init() {
	logsCmd.Flags().BoolP("follow", "f", false, "Specify if the logs should be streamed.")
	logsCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
}


================================================
FILE: cmd/kubeless/function/top.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"encoding/json"
	"fmt"
	"io"
	"sort"
	"time"

	"github.com/ghodss/yaml"
	"github.com/gosuri/uitable"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/client-go/kubernetes"

	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	"github.com/kubeless/kubeless/pkg/client/clientset/versioned"
	"github.com/kubeless/kubeless/pkg/utils"
)

var topCmd = &cobra.Command{
	Use:     "top",
	Aliases: []string{"stats"},
	Short:   "display function metrics",
	Long:    `display function metrics`,
	Run: func(cmd *cobra.Command, args []string) {
		functionName, err := cmd.Flags().GetString("function")
		if err != nil {
			logrus.Fatal(err)
		}
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		}
		output, err := cmd.Flags().GetString("out")
		if err != nil {
			logrus.Fatal(err.Error())
		}

		apiV1Client := utils.GetClientOutOfCluster()
		kubelessClient, err := utils.GetKubelessClientOutCluster()
		handler := &utils.PrometheusMetricsHandler{}

		err = doTop(cmd.OutOrStdout(), kubelessClient, apiV1Client, handler, ns, functionName, output)
		if err != nil {
			logrus.Fatal(err.Error())
		}
	},
}

func init() {
	topCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
	topCmd.Flags().StringP("function", "f", "", "Specify the function")
	topCmd.Flags().StringP("out", "o", "", "Output format. One of: json|yaml")
}

func doTop(w io.Writer, kubelessClient versioned.Interface, apiV1Client kubernetes.Interface, handler utils.MetricsRetriever, ns, functionName, output string) error {
	functions, err := getFunctions(kubelessClient, ns, functionName)
	if err != nil {
		return fmt.Errorf("Error listing functions: %v", err)
	}

	ch := make(chan []*utils.Metric, len(functions))
	for _, f := range functions {
		go func(f *kubelessApi.Function) {
			ch <- utils.GetFunctionMetrics(apiV1Client, handler, ns, f.ObjectMeta.Name)
		}(f)
	}

	var metrics []*utils.Metric

	i := 0
	for i < len(functions) {
		select {
		case r := <-ch:
			metrics = append(metrics, r...)
			i++
		// timeout all go routines after 5 seconds to avoid hanging at the cmd line
		case <-time.After(5 * time.Second):
			i = len(functions)
		}
	}

	// sort the results - useful when using 'watch kubeless function top'
	sort.Slice(metrics, func(i, j int) bool {
		return metrics[i].FunctionName < metrics[j].FunctionName
	})
	return printTop(w, metrics, apiV1Client, output)
}

func printTop(w io.Writer, metrics []*utils.Metric, cli kubernetes.Interface, output string) error {
	if output == "" {
		table := uitable.New()
		table.MaxColWidth = 50
		table.Wrap = true
		table.AddRow("NAME", "NAMESPACE", "METHOD", "TOTAL_CALLS", "TOTAL_FAILURES", "TOTAL_DURATION_SECONDS", "AVG_DURATION_SECONDS", "MESSAGE")
		for _, f := range metrics {
			if f.Message != "" {
				table.AddRow(f.FunctionName, f.Namespace, "", "", "", "", "", f.Message)
			} else {
				table.AddRow(f.FunctionName, f.Namespace, f.Method, f.TotalCalls, f.TotalFailures, f.TotalDurationSeconds, f.AvgDurationSeconds, "")
			}
		}
		fmt.Fprintln(w, table)
	} else {
		switch output {
		case "json":
			b, err := json.MarshalIndent(metrics, "", "  ")
			if err != nil {
				return err
			}
			fmt.Fprintln(w, string(b))
		case "yaml":
			b, err := yaml.Marshal(metrics)
			if err != nil {
				return err
			}
			fmt.Fprintln(w, string(b))
		default:
			return fmt.Errorf("Wrong output format. Please use only json|yaml")
		}
	}
	return nil
}


================================================
FILE: cmd/kubeless/function/top_test.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	appsv1 "k8s.io/api/apps/v1"
	v1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/fake"

	kubelessApi "github.com/kubeless/kubeless/pkg/apis/kubeless/v1beta1"
	"github.com/kubeless/kubeless/pkg/client/clientset/versioned"
	fFake "github.com/kubeless/kubeless/pkg/client/clientset/versioned/fake"
	"github.com/kubeless/kubeless/pkg/utils"
)

type testMetricsHandler struct{}

// handler used for testing purposes only
// satisfies the MetricsRetriever interface, gets metrics from the test http server (URL to test http server stored in svc.SelfLink field)
func (h *testMetricsHandler) GetRawMetrics(apiClient kubernetes.Interface, namespace, functionName string) ([]byte, error) {
	svc, err := apiClient.CoreV1().Services(namespace).Get(functionName, metav1.GetOptions{})
	if err != nil {
		return []byte{}, err
	}
	b, err := http.Get(svc.SelfLink)
	if err != nil {
		return nil, err
	}
	defer b.Body.Close()
	return ioutil.ReadAll(b.Body)
}

func topOutput(t *testing.T, client versioned.Interface, apiV1Client kubernetes.Interface, h utils.MetricsRetriever, ns, functionName, output string) string {
	var buf bytes.Buffer

	if err := doTop(&buf, client, apiV1Client, h, ns, functionName, output); err != nil {
		t.Fatalf("doTop returned error: %v", err)
	}

	return buf.String()
}

func TestTop(t *testing.T) {

	// setup test server to serve the /metrics endpoint
	ts2 := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w,
			`# HELP go_gc_duration_seconds A summary of the GC invocation durations.
			# TYPE go_gc_duration_seconds summary
			go_gc_duration_seconds{quantile="0"} 1.6846e-05
			go_gc_duration_seconds{quantile="0.25"} 3.9124e-05
			go_gc_duration_seconds{quantile="0.5"} 0.000147183
			go_gc_duration_seconds{quantile="0.75"} 0.000958419
			go_gc_duration_seconds{quantile="1"} 0.00796035
			go_gc_duration_seconds_sum 2.50781303
			go_gc_duration_seconds_count 3424
			# HELP go_goroutines Number of goroutines that currently exist.
			# TYPE go_goroutines gauge
			go_goroutines 7
			# HELP go_info Information about the Go environment.
			# TYPE go_info gauge
			go_info{version="go1.10.2"} 1
			# HELP go_memstats_alloc_bytes Number of bytes allocated and still in use.
			# TYPE go_memstats_alloc_bytes gauge
			go_memstats_alloc_bytes 2.28336e+06
			# HELP go_memstats_alloc_bytes_total Total number of bytes allocated, even if freed.
			# TYPE go_memstats_alloc_bytes_total counter
			go_memstats_alloc_bytes_total 9.9682544e+09
			# HELP go_memstats_buck_hash_sys_bytes Number of bytes used by the profiling bucket hash table.
			# TYPE go_memstats_buck_hash_sys_bytes gauge
			go_memstats_buck_hash_sys_bytes 1.500081e+06
			# HELP go_memstats_frees_total Total number of frees.
			# TYPE go_memstats_frees_total counter
			go_memstats_frees_total 1.2698678e+07
			# HELP go_memstats_gc_cpu_fraction The fraction of this program's available CPU time used by the GC since the program started.
			# TYPE go_memstats_gc_cpu_fraction gauge
			go_memstats_gc_cpu_fraction 0.0001214506861340198
			# HELP go_memstats_gc_sys_bytes Number of bytes used for garbage collection system metadata.
			# TYPE go_memstats_gc_sys_bytes gauge
			go_memstats_gc_sys_bytes 405504
			# HELP go_memstats_heap_alloc_bytes Number of heap bytes allocated and still in use.
			# TYPE go_memstats_heap_alloc_bytes gauge
			go_memstats_heap_alloc_bytes 2.28336e+06
			# HELP go_memstats_heap_idle_bytes Number of heap bytes waiting to be used.
			# TYPE go_memstats_heap_idle_bytes gauge
			go_memstats_heap_idle_bytes 2.6624e+06
			# HELP go_memstats_heap_inuse_bytes Number of heap bytes that are in use.
			# TYPE go_memstats_heap_inuse_bytes gauge
			go_memstats_heap_inuse_bytes 3.072e+06
			# HELP go_memstats_heap_objects Number of allocated objects.
			# TYPE go_memstats_heap_objects gauge
			go_memstats_heap_objects 6280
			# HELP go_memstats_heap_released_bytes Number of heap bytes released to OS.
			# TYPE go_memstats_heap_released_bytes gauge
			go_memstats_heap_released_bytes 0
			# HELP go_memstats_heap_sys_bytes Number of heap bytes obtained from system.
			# TYPE go_memstats_heap_sys_bytes gauge
			go_memstats_heap_sys_bytes 5.7344e+06
			# HELP go_memstats_last_gc_time_seconds Number of seconds since 1970 of last garbage collection.
			# TYPE go_memstats_last_gc_time_seconds gauge
			go_memstats_last_gc_time_seconds 1.528573398809276e+09
			# HELP go_memstats_lookups_total Total number of pointer lookups.
			# TYPE go_memstats_lookups_total counter
			go_memstats_lookups_total 88701
			# HELP go_memstats_mallocs_total Total number of mallocs.
			# TYPE go_memstats_mallocs_total counter
			go_memstats_mallocs_total 1.2704958e+07
			# HELP go_memstats_mcache_inuse_bytes Number of bytes in use by mcache structures.
			# TYPE go_memstats_mcache_inuse_bytes gauge
			go_memstats_mcache_inuse_bytes 3472
			# HELP go_memstats_mcache_sys_bytes Number of bytes used for mcache structures obtained from system.
			# TYPE go_memstats_mcache_sys_bytes gauge
			go_memstats_mcache_sys_bytes 16384
			# HELP go_memstats_mspan_inuse_bytes Number of bytes in use by mspan structures.
			# TYPE go_memstats_mspan_inuse_bytes gauge
			go_memstats_mspan_inuse_bytes 25688
			# HELP go_memstats_mspan_sys_bytes Number of bytes used for mspan structures obtained from system.
			# TYPE go_memstats_mspan_sys_bytes gauge
			go_memstats_mspan_sys_bytes 32768
			# HELP go_memstats_next_gc_bytes Number of heap bytes when next garbage collection will take place.
			# TYPE go_memstats_next_gc_bytes gauge
			go_memstats_next_gc_bytes 4.194304e+06
			# HELP go_memstats_other_sys_bytes Number of bytes used for other system allocations.
			# TYPE go_memstats_other_sys_bytes gauge
			go_memstats_other_sys_bytes 738631
			# HELP go_memstats_stack_inuse_bytes Number of bytes in use by the stack allocator.
			# TYPE go_memstats_stack_inuse_bytes gauge
			go_memstats_stack_inuse_bytes 557056
			# HELP go_memstats_stack_sys_bytes Number of bytes obtained from system for stack allocator.
			# TYPE go_memstats_stack_sys_bytes gauge
			go_memstats_stack_sys_bytes 557056
			# HELP go_memstats_sys_bytes Number of bytes obtained from system.
			# TYPE go_memstats_sys_bytes gauge
			go_memstats_sys_bytes 8.984824e+06
			# HELP go_threads Number of OS threads created.
			# TYPE go_threads gauge
			go_threads 10
			# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
			# TYPE process_cpu_seconds_total counter
			process_cpu_seconds_total 25.88
			# HELP process_max_fds Maximum number of open file descriptors.
			# TYPE process_max_fds gauge
			process_max_fds 1.048576e+06
			# HELP process_open_fds Number of open file descriptors.
			# TYPE process_open_fds gauge
			process_open_fds 8
			# HELP process_resident_memory_bytes Resident memory size in bytes.
			# TYPE process_resident_memory_bytes gauge
			process_resident_memory_bytes 1.3942784e+07
			# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
			# TYPE process_start_time_seconds gauge
			process_start_time_seconds 1.52853941225e+09
			# HELP process_virtual_memory_bytes Virtual memory size in bytes.
			# TYPE process_virtual_memory_bytes gauge
			process_virtual_memory_bytes 1.57294592e+08
			# HELP promhttp_metric_handler_requests_in_flight Current number of scrapes being served.
			# TYPE promhttp_metric_handler_requests_in_flight gauge
			promhttp_metric_handler_requests_in_flight 1
			# HELP promhttp_metric_handler_requests_total Total number of scrapes by HTTP status code.
			# TYPE promhttp_metric_handler_requests_total counter
			promhttp_metric_handler_requests_total{code="200"} 10798
			promhttp_metric_handler_requests_total{code="500"} 0
			promhttp_metric_handler_requests_total{code="503"} 0

`)
	}))
	defer ts2.Close()

	// setup test server to serve the /metrics endpoint
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w,
			`# HELP process_virtual_memory_bytes Virtual memory size in bytes.
			# TYPE process_virtual_memory_bytes gauge
			process_virtual_memory_bytes 815255552.0
			# HELP process_resident_memory_bytes Resident memory size in bytes.
			# TYPE process_resident_memory_bytes gauge
			process_resident_memory_bytes 25001984.0
			# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
			# TYPE process_start_time_seconds gauge
			process_start_time_seconds 1528507334.03
			# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
			# TYPE process_cpu_seconds_total counter
			process_cpu_seconds_total 54.72
			# HELP process_open_fds Number of open file descriptors.
			# TYPE process_open_fds gauge
			process_open_fds 8.0
			# HELP process_max_fds Maximum number of open file descriptors.
			# TYPE process_max_fds gauge
			process_max_fds 1048576.0
			# HELP python_info Python platform information
			# TYPE python_info gauge
			python_info{implementation="CPython",major="2",minor="7",patchlevel="9",version="2.7.9"} 1.0
			# HELP function_failures_total Number of exceptions in user function
			# TYPE function_failures_total counter
			function_failures_total{method="GET"} 0.0
			function_failures_total{method="POST"} 0.0
			# HELP function_calls_total Number of calls to user function
			# TYPE function_calls_total counter
			function_calls_total{method="GET"} 254.0
			function_calls_total{method="POST"} 296.0
			# HELP function_duration_seconds Duration of user function in seconds
			# TYPE function_duration_seconds histogram
			function_duration_seconds_bucket{le="0.005",method="GET"} 8.0
			function_duration_seconds_bucket{le="0.01",method="GET"} 191.0
			function_duration_seconds_bucket{le="0.025",method="GET"} 248.0
			function_duration_seconds_bucket{le="0.05",method="GET"} 253.0
			function_duration_seconds_bucket{le="0.075",method="GET"} 253.0
			function_duration_seconds_bucket{le="0.1",method="GET"} 253.0
			function_duration_seconds_bucket{le="0.25",method="GET"} 254.0
			function_duration_seconds_bucket{le="0.5",method="GET"} 254.0
			function_duration_seconds_bucket{le="0.75",method="GET"} 254.0
			function_duration_seconds_bucket{le="1.0",method="GET"} 254.0
			function_duration_seconds_bucket{le="2.5",method="GET"} 254.0
			function_duration_seconds_bucket{le="5.0",method="GET"} 254.0
			function_duration_seconds_bucket{le="7.5",method="GET"} 254.0
			function_duration_seconds_bucket{le="10.0",method="GET"} 254.0
			function_duration_seconds_bucket{le="+Inf",method="GET"} 254.0
			function_duration_seconds_count{method="GET"} 254.0
			function_duration_seconds_sum{method="GET"} 2.863368272781372
			function_duration_seconds_bucket{le="0.005",method="POST"} 1.0
			function_duration_seconds_bucket{le="0.01",method="POST"} 157.0
			function_duration_seconds_bucket{le="0.025",method="POST"} 296.0
			function_duration_seconds_bucket{le="0.05",method="POST"} 296.0
			function_duration_seconds_bucket{le="0.075",method="POST"} 296.0
			function_duration_seconds_bucket{le="0.1",method="POST"} 296.0
			function_duration_seconds_bucket{le="0.25",method="POST"} 296.0
			function_duration_seconds_bucket{le="0.5",method="POST"} 296.0
			function_duration_seconds_bucket{le="0.75",method="POST"} 296.0
			function_duration_seconds_bucket{le="1.0",method="POST"} 296.0
			function_duration_seconds_bucket{le="2.5",method="POST"} 296.0
			function_duration_seconds_bucket{le="5.0",method="POST"} 296.0
			function_duration_seconds_bucket{le="7.5",method="POST"} 296.0
			function_duration_seconds_bucket{le="10.0",method="POST"} 296.0
			function_duration_seconds_bucket{le="+Inf",method="POST"} 296.0
			function_duration_seconds_count{method="POST"} 296.0
			function_duration_seconds_sum{method="POST"} 3.4116291999816895

`)
	}))
	defer ts.Close()

	function1Name := "pyFunc"
	function2Name := "goFunc"
	namespace := "myns"

	listObj := kubelessApi.FunctionList{
		Items: []*kubelessApi.Function{
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:      function1Name,
					Namespace: namespace,
				},
				Spec: kubelessApi.FunctionSpec{
					Handler:  "fhandler",
					Function: function1Name,
					Runtime:  "pyruntime",
					Deps:     "pydeps",
					Deployment: appsv1.Deployment{
						Spec: appsv1.DeploymentSpec{
							Template: v1.PodTemplateSpec{
								Spec: v1.PodSpec{
									Containers: []v1.Container{{}},
								},
							},
						},
					},
				},
			},
			{
				ObjectMeta: metav1.ObjectMeta{
					Name:      function2Name,
					Namespace: namespace,
				},
				Spec: kubelessApi.FunctionSpec{
					Handler:  "gohandler",
					Function: function2Name,
					Runtime:  "goruntime",
					Deps:     "godeps",
					Deployment: appsv1.Deployment{
						Spec: appsv1.DeploymentSpec{
							Template: v1.PodTemplateSpec{
								Spec: v1.PodSpec{
									Containers: []v1.Container{{}},
								},
							},
						},
					},
				},
			},
		},
	}

	client := fFake.NewSimpleClientset(listObj.Items[0], listObj.Items[1])

	deploymentPy := appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      function1Name,
			Namespace: namespace,
		},
		Status: appsv1.DeploymentStatus{
			Replicas:      int32(1),
			ReadyReplicas: int32(1),
		},
	}
	deploymentGo := appsv1.Deployment{
		ObjectMeta: metav1.ObjectMeta{
			Name:      function2Name,
			Namespace: namespace,
		},
		Status: appsv1.DeploymentStatus{
			Replicas:      int32(1),
			ReadyReplicas: int32(1),
		},
	}
	serviceGo := v1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Name:      function2Name,
			Namespace: namespace,
			SelfLink:  ts2.URL,
		},
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{
				{
					Name:       "p1",
					Port:       int32(8080),
					TargetPort: intstr.FromInt(8080),
					NodePort:   0,
					Protocol:   v1.ProtocolTCP,
				},
			},
		},
	}
	servicePy := v1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Name:      function1Name,
			Namespace: namespace,
			SelfLink:  ts.URL,
		},
		Spec: v1.ServiceSpec{
			Ports: []v1.ServicePort{
				{
					Name:       "p1",
					Port:       int32(8080),
					TargetPort: intstr.FromInt(8080),
					NodePort:   0,
					Protocol:   v1.ProtocolTCP,
				},
			},
		},
	}

	apiV1Client := fake.NewSimpleClientset(&deploymentPy, &servicePy, &deploymentGo, &serviceGo)

	handler := &testMetricsHandler{}

	// List multiple functions
	output := topOutput(t, client, apiV1Client, handler, namespace, "", "")
	t.Log("output is", output)

	if !strings.Contains(output, function1Name) || !strings.Contains(output, function2Name) || !strings.Contains(output, namespace) {
		t.Errorf("table output didn't match FUNCTION or NAMESPACE")
	}
	if !strings.Contains(output, "GET") || !strings.Contains(output, "POST") {
		t.Errorf("table output didn't match on METHOD")
	}
	if !strings.Contains(output, "2.86336") || !strings.Contains(output, "3.41162") {
		t.Errorf("table output didn't match on TOTAL_DURATION_SECONDS")
	}
	// verify calculated fields
	if !strings.Contains(output, "0.0112731") || !strings.Contains(output, "0.0115257") {
		t.Errorf("table output didn't match on AVG_DURATION_SECONDS")
	}

	// Get single function
	output = topOutput(t, client, apiV1Client, handler, namespace, function2Name, "")
	t.Log("output is", output)

	if strings.Contains(output, function1Name) || !strings.Contains(output, function2Name) || !strings.Contains(output, namespace) {
		t.Errorf("table output didn't match FUNCTION or NAMESPACE")
	}

	// json output
	output = topOutput(t, client, apiV1Client, handler, namespace, "", "json")
	t.Log("output is", output)

	if !strings.Contains(output, function1Name) || !strings.Contains(output, function2Name) || !strings.Contains(output, namespace) {
		t.Errorf("table output didn't match FUNCTION or NAMESPACE")
	}
	if !strings.Contains(output, "GET") || !strings.Contains(output, "POST") {
		t.Errorf("table output didn't match on METHOD")
	}
	if !strings.Contains(output, "2.86336") || !strings.Contains(output, "3.41162") {
		t.Errorf("table output didn't match on TOTAL_DURATION_SECONDS")
	}
	// verify calculated fields
	if !strings.Contains(output, "0.0112731") || !strings.Contains(output, "0.0115257") {
		t.Errorf("table output didn't match on AVG_DURATION_SECONDS")
	}

	// yaml output
	output = topOutput(t, client, apiV1Client, handler, namespace, "", "yaml")
	t.Log("output is", output)

	if !strings.Contains(output, function1Name) || !strings.Contains(output, function2Name) || !strings.Contains(output, namespace) {
		t.Errorf("table output didn't match FUNCTION or NAMESPACE")
	}
	if !strings.Contains(output, "GET") || !strings.Contains(output, "POST") {
		t.Errorf("table output didn't match on METHOD")
	}
	if !strings.Contains(output, "2.86336") || !strings.Contains(output, "3.41162") {
		t.Errorf("table output didn't match on TOTAL_DURATION_SECONDS")
	}
	// verify calculated fields
	if !strings.Contains(output, "0.0112731") || !strings.Contains(output, "0.0115257") {
		t.Errorf("table output didn't match on AVG_DURATION_SECONDS")
	}

}


================================================
FILE: cmd/kubeless/function/update.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package function

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/ghodss/yaml"
	"github.com/kubeless/kubeless/pkg/langruntime"
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

var updateCmd = &cobra.Command{
	Use:   "update <function_name> FLAG",
	Short: "update a function on Kubeless",
	Long:  `update a function on Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cli := utils.GetClientOutOfCluster()
		apiExtensionsClientset := utils.GetAPIExtensionsClientOutOfCluster()
		config, err := utils.GetKubelessConfig(cli, apiExtensionsClientset)
		if err != nil {
			logrus.Fatalf("Unable to read the configmap: %v", err)
		}

		var lr = langruntime.New(config)
		lr.ReadConfigMap()

		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - function name")
		}
		funcName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		var nsArg string
		if ns == "" {
			ns = utils.GetDefaultNamespace()
		} else {
			nsArg = fmt.Sprintf(" -n %s", ns)
		}

		handler, err := cmd.Flags().GetString("handler")
		if err != nil {
			logrus.Fatal(err)
		}

		file, err := cmd.Flags().GetString("from-file")
		if err != nil {
			logrus.Fatal(err)
		}

		secrets, err := cmd.Flags().GetStringSlice("secrets")
		if err != nil {
			logrus.Fatal(err)
		}

		serviceAccount, err := cmd.Flags().GetString("service-account")
		if err != nil {
			logrus.Fatal(err)
		}

		runtime, err := cmd.Flags().GetString("runtime")
		if err != nil {
			logrus.Fatal(err)
		}

		if runtime != "" && !lr.IsValidRuntime(runtime) {
			logrus.Fatalf("Invalid runtime: %s. Supported runtimes are: %s",
				runtime, strings.Join(lr.GetRuntimes(), ", "))
		}

		labels, err := cmd.Flags().GetStringSlice("label")
		if err != nil {
			logrus.Fatal(err)
		}

		envs, err := cmd.Flags().GetStringSlice("env")
		if err != nil {
			logrus.Fatal(err)
		}
		runtimeImage, err := cmd.Flags().GetString("runtime-image")
		if err != nil {
			logrus.Fatal(err)
		}

		imagePullPolicy, err := cmd.Flags().GetString("image-pull-policy")
		if err != nil {
			logrus.Fatal(err)
		}

		if imagePullPolicy != "IfNotPresent" && imagePullPolicy != "Always" && imagePullPolicy != "Never" {
			err := fmt.Errorf("image-pull-policy must be {IfNotPresent|Always|Never}")
			logrus.Fatal(err)
		}

		mem, err := cmd.Flags().GetString("memory")
		if err != nil {
			logrus.Fatal(err)
		}

		cpu, err := cmd.Flags().GetString("cpu")
		if err != nil {
			logrus.Fatal(err)
		}

		timeout, err := cmd.Flags().GetString("timeout")
		if err != nil {
			logrus.Fatal(err)
		}

		deps, err := cmd.Flags().GetString("dependencies")
		if err != nil {
			logrus.Fatal(err)
		}
		funcDeps := ""
		if deps != "" {
			contentType, err := utils.GetContentType(deps)
			if err != nil {
				logrus.Fatal(err)
			}
			funcDeps, _, err = utils.ParseContent(deps, contentType)
			if err != nil {
				logrus.Fatal(err)
			}
		}
		headless, err := cmd.Flags().GetBool("headless")
		if err != nil {
			logrus.Fatal(err)
		}
		port, err := cmd.Flags().GetInt32("port")
		if err != nil {
			logrus.Fatal(err)
		}
		if port <= 0 || port > 65535 {
			logrus.Fatalf("Invalid port number %d specified", port)
		}
		servicePort, err := cmd.Flags().GetInt32("servicePort")
		if err != nil {
			logrus.Fatal(err)
		}
		if servicePort < 0 || servicePort > 65535 {
			logrus.Fatalf("Invalid servicePort number %d specified", servicePort)
		}

		output, err := cmd.Flags().GetString("output")
		if err != nil {
			logrus.Fatal(err)
		}

		dryrun, err := cmd.Flags().GetBool("dryrun")
		if err != nil {
			logrus.Fatal(err)
		}

		nodeSelectors, err := cmd.Flags().GetStringSlice("node-selectors")
		if err != nil {
			logrus.Fatal(err)
		}

		previousFunction, err := utils.GetFunction(funcName, ns)
		if err != nil {
			logrus.Fatal(err)
		}

		f, err := getFunctionDescription(funcName, ns, handler, file, funcDeps, runtime, runtimeImage, mem, cpu, timeout, imagePullPolicy, serviceAccount, port, servicePort, headless, envs, labels, secrets, nodeSelectors, previousFunction)
		if err != nil {
			logrus.Fatal(err)
		}

		if dryrun == true {
			if output == "json" {
				j, err := json.MarshalIndent(f, "", "    ")
				if err != nil {
					logrus.Fatal(err)
				}
				fmt.Println(string(j[:]))
				return
			} else if output == "yaml" {
				y, err := yaml.Marshal(f)
				if err != nil {
					logrus.Fatal(err)
				}
				fmt.Println(string(y[:]))
				return
			} else {
				logrus.Infof("Output format needs to be yaml or json")
				return
			}
		}

		kubelessClient, err := utils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatal(err)
		}
		logrus.Infof("Redeploying function...")
		err = utils.PatchFunctionCustomResource(kubelessClient, f)
		if err != nil {
			logrus.Fatal(err)
		}
		logrus.Infof("Function %s submitted for deployment", funcName)
		logrus.Infof("Check the deployment status executing 'kubeless function ls %s%s'", funcName, nsArg)
	},
}

func init() {
	updateCmd.Flags().StringP("runtime", "r", "", "Specify runtime")
	updateCmd.Flags().StringP("handler", "", "", "Specify handler")
	updateCmd.Flags().StringP("from-file", "f", "", "Specify code file or a URL to the code file")
	updateCmd.Flags().StringP("memory", "", "", "Request amount of memory for the function")
	updateCmd.Flags().StringP("cpu", "", "", "Request amount of cpu for the function.")
	updateCmd.Flags().StringSliceP("label", "l", []string{}, "Specify labels of the function")
	updateCmd.Flags().StringSliceP("secrets", "", []string{}, "Specify Secrets to be mounted to the functions container. For example: --secrets mySecret")
	updateCmd.Flags().StringSliceP("env", "e", []string{}, "Specify environment variable of the function")
	updateCmd.Flags().StringSliceP("node-selectors", "", []string{}, "Specify node selectors for the function")
	updateCmd.Flags().StringP("service-account", "", "", "Specify service account for the function. For example: --service-account controller-acct")
	updateCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
	updateCmd.Flags().StringP("dependencies", "d", "", "Specify a file containing list of dependencies for the function")
	updateCmd.Flags().StringP("runtime-image", "", "", "Custom runtime image")
	updateCmd.Flags().StringP("image-pull-policy", "", "Always", "Image pull policy")
	updateCmd.Flags().StringP("timeout", "", "180", "Maximum timeout (in seconds) for the function to complete its execution")
	updateCmd.Flags().Bool("headless", false, "Deploy http-based function without a single service IP and load balancing support from Kubernetes. See: https://kubernetes.io/docs/concepts/services-networking/service/#headless-services")
	updateCmd.Flags().Int32("port", 8080, "Deploy http-based function with a custom port")
	updateCmd.Flags().Int32("servicePort", 0, "Deploy http-based function with a custom service port")
	updateCmd.Flags().Bool("dryrun", false, "Output JSON manifest of the function without creating it")
	updateCmd.Flags().StringP("output", "o", "yaml", "Output format")
}


================================================
FILE: cmd/kubeless/getserverconfig/getServerConfig.go
================================================
package getserverconfig

import (
	"strings"

	"github.com/kubeless/kubeless/pkg/langruntime"
	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

// GetServerConfigCmd contains first-class command for displaying the current server config
var GetServerConfigCmd = &cobra.Command{
	Use:   "get-server-config",
	Short: "Print the current configuration of the controller",
	Long:  ``,
	Run: func(cmd *cobra.Command, args []string) {
		cli := utils.GetClientOutOfCluster()
		apiExtensionsClientset := utils.GetAPIExtensionsClientOutOfCluster()
		config, err := utils.GetKubelessConfig(cli, apiExtensionsClientset)
		if err != nil {
			logrus.Fatalf("Unable to read the configmap: %v", err)
		}

		var lr = langruntime.New(config)
		lr.ReadConfigMap()

		logrus.Info("Current Server Config:")
		logrus.Infof("Supported Runtimes are: %s",
			strings.Join(lr.GetRuntimes(), ", "))
	},
}


================================================
FILE: cmd/kubeless/kubeless.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

// Serverless framework for Kubernetes.
package main

import (
	"os"

	"github.com/kubeless/kubeless/cmd/kubeless/autoscale"
	"github.com/kubeless/kubeless/cmd/kubeless/completion"
	"github.com/kubeless/kubeless/cmd/kubeless/function"
	"github.com/kubeless/kubeless/cmd/kubeless/getserverconfig"
	"github.com/kubeless/kubeless/cmd/kubeless/topic"
	"github.com/kubeless/kubeless/cmd/kubeless/trigger"
	"github.com/kubeless/kubeless/cmd/kubeless/version"
	"github.com/spf13/cobra"
)

var globalUsage = `` //TODO: add explanation

func newRootCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:   "kubeless",
		Short: "Serverless framework for Kubernetes",
		Long:  globalUsage,
	}

	cmd.AddCommand(function.FunctionCmd, topic.TopicCmd, version.VersionCmd, autoscale.AutoscaleCmd, getserverconfig.GetServerConfigCmd, trigger.TriggerCmd, completion.CompletionCmd)
	return cmd
}

func main() {
	cmd := newRootCmd()
	if err := cmd.Execute(); err != nil {
		os.Exit(1)
	}
}


================================================
FILE: cmd/kubeless/topic/topic.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package topic

import (
	"github.com/spf13/cobra"
)

// TopicCmd contains first-class command for topic
var TopicCmd = &cobra.Command{
	Use:   "topic SUBCOMMAND",
	Short: "manage message topics in Kubeless",
	Long:  `topic command allows user to list, create, delete topics on Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cmd.Help()
	},
}

func init() {
	cmds := []*cobra.Command{topicCreateCmd, topicDeleteCmd, topicListCmd, topicPublishCmd}

	for _, cmd := range cmds {
		TopicCmd.AddCommand(cmd)
		cmd.Flags().StringP("kafka-namespace", "", "kubeless", "Namespace where kafka-controller is deployed. It will default to 'kubeless'")
	}
}


================================================
FILE: cmd/kubeless/topic/topicCreate.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package topic

import (
	"fmt"
	"io"

	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/api/core/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
)

var topicCreateCmd = &cobra.Command{
	Use:   "create <topic_name> FLAG",
	Short: "create a topic to Kubeless",
	Long:  `create a topic to Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - topic name")
		}
		ctlNamespace, err := cmd.Flags().GetString("kafka-namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		topicName := args[0]

		conf, err := utils.BuildOutOfClusterConfig()
		if err != nil {
			logrus.Fatal(err)
		}

		k8sClientSet := utils.GetClientOutOfCluster()

		err = createTopic(conf, k8sClientSet, ctlNamespace, topicName, cmd.OutOrStdout())
		if err != nil {
			logrus.Fatal(err)
		}
	},
}

func createTopic(conf *rest.Config, clientset kubernetes.Interface, ctlNamespace, topicName string, out io.Writer) error {
	command := []string{
		"bash", "/opt/bitnami/kafka/bin/kafka-topics.sh",
		"--zookeeper", "zookeeper." + ctlNamespace + ":2181",
		"--replication-factor", "1",
		"--partitions", "1",
		"--create",
		"--topic", topicName,
	}
	return execCommand(conf, clientset, ctlNamespace, command, out)
}

// wrapper of kubectl exec
// execCommand executes a command to kafka pod
func execCommand(conf *rest.Config, k8sClientSet kubernetes.Interface, ctlNamespace string, command []string, out io.Writer) error {
	pods, err := utils.GetPodsByLabel(k8sClientSet, ctlNamespace, "kubeless", "kafka")
	if err != nil {
		return fmt.Errorf("Can't find the kafka pod: %v", err)
	} else if len(pods.Items) == 0 {
		return fmt.Errorf("Can't find any kafka pod")
	}

	cmd := utils.Cmd{
		Stdout: out,
		Stderr: out,
	}
	rt, err := utils.ExecRoundTripper(conf, cmd.RoundTripCallback)
	if err != nil {
		return err
	}

	opts := v1.PodExecOptions{
		Stdin:     false,
		Stdout:    true,
		Stderr:    true,
		Container: "broker",
		Command:   command,
	}

	req, err := utils.Exec(k8sClientSet.Core(), pods.Items[0].Name, ctlNamespace, opts)
	if err != nil {
		return err
	}

	_, err = rt.RoundTrip(req)
	return err
}


================================================
FILE: cmd/kubeless/topic/topicDelete.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package topic

import (
	"io"

	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
)

var topicDeleteCmd = &cobra.Command{
	Use:   "delete <topic_name>",
	Short: "delete a topic from Kubeless",
	Long:  `delete a topic from Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - topic name")
		}
		ctlNamespace, err := cmd.Flags().GetString("kafka-namespace")
		if err != nil {
			logrus.Fatal(err)
		}

		topicName := args[0]

		conf, err := utils.BuildOutOfClusterConfig()
		if err != nil {
			logrus.Fatal(err)
		}

		k8sClientSet := utils.GetClientOutOfCluster()

		err = deleteTopic(conf, k8sClientSet, ctlNamespace, topicName, cmd.OutOrStdout())
		if err != nil {
			logrus.Fatal(err)
		}
	},
}

func deleteTopic(conf *rest.Config, clientset kubernetes.Interface, ctlNamespace, topicName string, out io.Writer) error {
	command := []string{
		"bash", "/opt/bitnami/kafka/bin/kafka-topics.sh",
		"--zookeeper", "zookeeper." + ctlNamespace + ":2181",
		"--delete",
		"--topic", topicName,
	}

	return execCommand(conf, clientset, ctlNamespace, command, out)
}


================================================
FILE: cmd/kubeless/topic/topicList.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package topic

import (
	"io"

	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
)

var topicListCmd = &cobra.Command{
	Use:     "list FLAG",
	Aliases: []string{"ls"},
	Short:   "list all topics created in Kubeless",
	Long:    `list all topics created in Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		ctlNamespace, err := cmd.Flags().GetString("kafka-namespace")
		if err != nil {
			logrus.Fatal(err)
		}

		conf, err := utils.BuildOutOfClusterConfig()
		if err != nil {
			logrus.Fatal(err)
		}

		k8sClientSet := utils.GetClientOutOfCluster()

		err = listTopic(conf, k8sClientSet, ctlNamespace, cmd.OutOrStdout())
		if err != nil {
			logrus.Fatal(err)
		}
	},
}

func listTopic(conf *rest.Config, clientset kubernetes.Interface, ctlNamespace string, out io.Writer) error {
	command := []string{
		"bash", "/opt/bitnami/kafka/bin/kafka-topics.sh",
		"--zookeeper", "zookeeper." + ctlNamespace + ":2181",
		"--list",
	}
	return execCommand(conf, clientset, ctlNamespace, command, out)
}


================================================
FILE: cmd/kubeless/topic/topicPublish.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package topic

import (
	"fmt"
	"io"

	"github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"k8s.io/api/core/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
)

var topicPublishCmd = &cobra.Command{
	Use:   "publish FLAG",
	Short: "publish message to a topic",
	Long:  `publish message to a topic`,
	Run: func(cmd *cobra.Command, args []string) {
		data, err := cmd.Flags().GetString("data")
		if err != nil {
			logrus.Fatal(err)
		}

		topic, err := cmd.Flags().GetString("topic")
		if err != nil {
			logrus.Fatal(err)
		}

		ctlNamespace, err := cmd.Flags().GetString("kafka-namespace")
		if err != nil {
			logrus.Fatal(err)
		}

		conf, err := utils.BuildOutOfClusterConfig()
		if err != nil {
			logrus.Fatal(err)
		}

		k8sClientSet := utils.GetClientOutOfCluster()

		err = publishTopic(conf, k8sClientSet, ctlNamespace, topic, data, cmd.OutOrStdout())
		if err != nil {
			logrus.Fatal(err)
		}
	},
}

func publishTopic(conf *rest.Config, clientset kubernetes.Interface, namespace, topic, data string, out io.Writer) error {
	command := []string{
		"bash", "/opt/bitnami/kafka/bin/kafka-console-producer.sh",
		"--broker-list", "localhost:9092",
		"--topic", topic,
	}

	// Can't just use `execCommand` since we want to specify stdin
	// TODO(gus): refactor better.

	pods, err := utils.GetPodsByLabel(clientset, namespace, "kubeless", "kafka")
	if err != nil {
		return fmt.Errorf("Can't find the kafka pod: %v", err)
	} else if len(pods.Items) == 0 {
		return fmt.Errorf("Can't find any kafka pod")
	}

	pRead, pWrite := io.Pipe()
	cmd := utils.Cmd{
		Stdin:  pRead,
		Stdout: out,
		Stderr: out,
	}
	rt, err := utils.ExecRoundTripper(conf, cmd.RoundTripCallback)
	if err != nil {
		return err
	}

	go func() {
		io.WriteString(pWrite, data+"\n")
		pWrite.Close()
	}()

	opts := v1.PodExecOptions{
		Stdin:     true,
		Stdout:    true,
		Stderr:    true,
		TTY:       true,
		Container: "broker",
		Command:   command,
	}

	req, err := utils.Exec(clientset.Core(), pods.Items[0].Name, namespace, opts)
	if err != nil {
		return err
	}

	_, err = rt.RoundTrip(req)
	return err
}

func init() {
	topicPublishCmd.Flags().StringP("data", "", "", "Specify data for function")
	topicPublishCmd.Flags().StringP("topic", "", "kubeless", "Specify topic name")
}


================================================
FILE: cmd/kubeless/trigger/cronjob/create.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package cronjob

import (
	"fmt"

	"github.com/robfig/cron"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	cronjobApi "github.com/kubeless/cronjob-trigger/pkg/apis/kubeless/v1beta1"
	cronjobUtils "github.com/kubeless/cronjob-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var createCmd = &cobra.Command{
	Use:   "create <cronjob_trigger_name> FLAG",
	Short: "Create a cron job trigger",
	Long:  `Create a cron job trigger`,
	Run: func(cmd *cobra.Command, args []string) {

		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - cronjob trigger name")
		}
		triggerName := args[0]

		schedule, err := cmd.Flags().GetString("schedule")
		if err != nil {
			logrus.Fatal(err)
		}

		if _, err := cron.ParseStandard(schedule); err != nil {
			logrus.Fatalf("Invalid value for --schedule. " + err.Error())
		}

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		functionName, err := cmd.Flags().GetString("function")
		if err != nil {
			logrus.Fatal(err)
		}

		dryrun, err := cmd.Flags().GetBool("dryrun")
		if err != nil {
			logrus.Fatal(err)
		}

		output, err := cmd.Flags().GetString("output")
		if err != nil {
			logrus.Fatal(err)
		}

		payload, err := cmd.Flags().GetString("payload")
		if err != nil {
			logrus.Fatal(err)
		}

		payloadFromFile, err := cmd.Flags().GetString("payload-from-file")
		if err != nil {
			logrus.Fatal(err)
		}

		if len(payload) > 0 && len(payloadFromFile) > 0 {
			err := "You can't provide both raw payload and a payload file"
			logrus.Fatal(err)
		}

		kubelessClient, err := kubelessUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		cronJobClient, err := cronjobUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		_, err = kubelessUtils.GetFunctionCustomResource(kubelessClient, functionName, ns)
		if err != nil {
			logrus.Fatalf("Unable to find Function %s in namespace %s. Error %s", functionName, ns, err)
		}

		parsedPayload, err := parsePayload(payload, payloadFromFile)
		if err != nil {
			logrus.Fatalf("Unable to parse the payload of Function %s in namespace %s. Error %s", functionName, ns, err)
		}

		cronJobTrigger := cronjobApi.CronJobTrigger{}
		cronJobTrigger.TypeMeta = metav1.TypeMeta{
			Kind:       "CronJobTrigger",
			APIVersion: "kubeless.io/v1beta1",
		}
		cronJobTrigger.ObjectMeta = metav1.ObjectMeta{
			Name:      triggerName,
			Namespace: ns,
		}
		cronJobTrigger.ObjectMeta.Labels = map[string]string{
			"created-by": "kubeless",
		}
		cronJobTrigger.Spec.FunctionName = functionName
		cronJobTrigger.Spec.Schedule = schedule
		cronJobTrigger.Spec.Payload = parsedPayload

		if dryrun == true {
			res, err := kubelessUtils.DryRunFmt(output, cronJobTrigger)
			if err != nil {
				logrus.Fatal(err)
			}
			fmt.Println(res)
			return
		}

		err = cronjobUtils.CreateCronJobCustomResource(cronJobClient, &cronJobTrigger)
		if err != nil {
			logrus.Fatalf("Failed to create cronjob trigger object %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("Cronjob trigger %s created in namespace %s successfully!", triggerName, ns)
	},
}

func init() {
	createCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the cronjob trigger")
	createCmd.Flags().StringP("schedule", "", "", "Specify schedule in cron format for scheduled function")
	createCmd.Flags().StringP("function", "", "", "Name of the function to be associated with trigger")
	createCmd.MarkFlagRequired("function")
	createCmd.MarkFlagRequired("schedule")
	createCmd.Flags().Bool("dryrun", false, "Output JSON manifest of the function without creating it")
	createCmd.Flags().StringP("output", "o", "yaml", "Output format")
	createCmd.Flags().StringP("payload", "p", "", "Specify a stringified JSON data to pass to function upon execution")
	createCmd.Flags().StringP("payload-from-file", "f", "", "Specify a payload file to use. It must be a JSON file")
}


================================================
FILE: cmd/kubeless/trigger/cronjob/cronjob_trigger.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package cronjob

import (
	"encoding/json"
	"fmt"
	"path/filepath"

	kubelessutil "github.com/kubeless/kubeless/pkg/utils"
	"github.com/spf13/cobra"
)

// CronjobTriggerCmd command for CronJob trigger commands
var CronjobTriggerCmd = &cobra.Command{
	Use:   "cronjob SUBCOMMAND",
	Short: "cronjob trigger specific operations",
	Long:  `cronjob trigger command allows user to create, list, update, delete cronjob triggers running on Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cmd.Help()
	},
}

func init() {
	CronjobTriggerCmd.AddCommand(createCmd)
	CronjobTriggerCmd.AddCommand(deleteCmd)
	CronjobTriggerCmd.AddCommand(listCmd)
	CronjobTriggerCmd.AddCommand(updateCmd)
}

func parsePayload(content string, file string) (interface{}, error) {
	if len(file) > 0 {
		content, err := getPayloadRawContent(file)
		if err != nil {
			return nil, err
		}

		return parsePayloadContent(content), nil
	}

	return parsePayloadContent(content), nil
}

func getPayloadRawContent(file string) (string, error) {
	contentType, err := kubelessutil.GetContentType(file)
	if err != nil {
		return "", err
	}

	content, _, err := kubelessutil.ParseContent(file, contentType)
	if err != nil {
		return "", err
	}

	ext := filepath.Ext(file)
	if ext != ".json" {
		return "", fmt.Errorf("Sorry, we can't parse %s files yet", ext)
	}

	return content, nil
}

func parsePayloadContent(raw string) interface{} {
	var payload map[string]interface{}

	err := json.Unmarshal([]byte(raw), &payload)
	if err != nil {
		return fmt.Errorf("Found an error during JSON parsing on your payload: %s", err)
	}

	return payload
}


================================================
FILE: cmd/kubeless/trigger/cronjob/delete.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package cronjob

import (
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	cronjobUtils "github.com/kubeless/cronjob-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
)

var deleteCmd = &cobra.Command{

	Use:   "delete <cronjob_trigger_name>",
	Short: "delete a cronjob trigger from Kubeless",
	Long:  `delete a cronjob trigger from Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - cronjob trigger name")
		}
		triggerName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		kubelessClient, err := cronjobUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatal(err)
		}
		err = cronjobUtils.DeleteCronJobCustomResource(kubelessClient, triggerName, ns)
		if err != nil {
			logrus.Fatalf("Failed to delete Cronjob trigger object %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("Cronjob trigger %s deleted from namespace %s successfully!", triggerName, ns)
	},
}

func init() {
	deleteCmd.Flags().StringP("namespace", "n", "", "Specify namespace of the Cronjob trigger")
}


================================================
FILE: cmd/kubeless/trigger/cronjob/list.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package cronjob

import (
	"fmt"
	"io"

	"github.com/gosuri/uitable"
	"github.com/kubeless/cronjob-trigger/pkg/client/clientset/versioned"
	cronjobUtils "github.com/kubeless/cronjob-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var listCmd = &cobra.Command{
	Use:     "list FLAG",
	Aliases: []string{"ls"},
	Short:   "list all Cronjob triggers deployed to Kubeless",
	Long:    `list all Cronjob triggers deployed to Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		kubelessClient, err := cronjobUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		if err := doList(cmd.OutOrStdout(), kubelessClient, ns); err != nil {
			logrus.Fatal(err.Error())
		}
	},
}

func init() {
	listCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
}

func doList(w io.Writer, kubelessClient versioned.Interface, ns string) error {
	triggersList, err := kubelessClient.KubelessV1beta1().CronJobTriggers(ns).List(metav1.ListOptions{})
	if err != nil {
		return err
	}
	table := uitable.New()
	table.MaxColWidth = 50
	table.Wrap = true
	table.AddRow("NAME", "NAMESPACE", "SCHEDULE", "FUNCTION NAME")
	for _, trigger := range triggersList.Items {
		table.AddRow(trigger.Name, trigger.Namespace, trigger.Spec.Schedule, trigger.Spec.FunctionName)
	}
	fmt.Fprintln(w, table)
	return nil
}


================================================
FILE: cmd/kubeless/trigger/cronjob/update.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package cronjob

import (
	"fmt"

	"github.com/robfig/cron"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	cronjobUtils "github.com/kubeless/cronjob-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
)

var updateCmd = &cobra.Command{
	Use:   "update <cronjob_trigger_name> FLAG",
	Short: "Update a cron job trigger",
	Long:  `Update a cron job trigger`,
	Run: func(cmd *cobra.Command, args []string) {

		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - cronjob trigger name")
		}
		triggerName := args[0]

		schedule, err := cmd.Flags().GetString("schedule")
		if err != nil {
			logrus.Fatal(err)
		}

		if schedule != "" {
			if _, err := cron.ParseStandard(schedule); err != nil {
				logrus.Fatalf("Invalid value for --schedule. " + err.Error())
			}
		}

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		functionName, err := cmd.Flags().GetString("function")
		if err != nil {
			logrus.Fatal(err)
		}

		dryrun, err := cmd.Flags().GetBool("dryrun")
		if err != nil {
			logrus.Fatal(err)
		}

		output, err := cmd.Flags().GetString("output")
		if err != nil {
			logrus.Fatal(err)
		}

		payload, err := cmd.Flags().GetString("payload")
		if err != nil {
			logrus.Fatal(err)
		}

		payloadFromFile, err := cmd.Flags().GetString("payload-from-file")
		if err != nil {
			logrus.Fatal(err)
		}

		if len(payload) > 0 && len(payloadFromFile) > 0 {
			err := "You can't provide both raw payload and a payload file"
			logrus.Fatal(err)
		}

		kubelessClient, err := kubelessUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		cronJobClient, err := cronjobUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		_, err = kubelessUtils.GetFunctionCustomResource(kubelessClient, functionName, ns)
		if err != nil {
			logrus.Fatalf("Unable to find Function %s in namespace %s. Error %s", triggerName, ns, err)
		}

		parsedPayload, err := parsePayload(payload, payloadFromFile)
		if err != nil {
			logrus.Fatalf("Unable to parse the payload of Function %s in namespace %s. Error %s", functionName, ns, err)
		}

		cronJobTrigger, err := cronjobUtils.GetCronJobCustomResource(cronJobClient, triggerName, ns)
		if err != nil {
			logrus.Fatalf("Unable to find Cronjob trigger %s in namespace %s. Error %s", triggerName, ns, err)
		}
		cronJobTrigger.Spec.FunctionName = functionName
		cronJobTrigger.Spec.Schedule = schedule
		cronJobTrigger.Spec.Payload = parsedPayload

		if dryrun == true {
			res, err := kubelessUtils.DryRunFmt(output, cronJobTrigger)
			if err != nil {
				logrus.Fatal(err)
			}
			fmt.Println(res)
			return
		}

		err = cronjobUtils.UpdateCronJobCustomResource(cronJobClient, cronJobTrigger)
		if err != nil {
			logrus.Fatalf("Failed to update cronjob trigger object %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("Cronjob trigger %s updated in namespace %s successfully!", triggerName, ns)
	},
}

func init() {
	updateCmd.Flags().StringP("namespace", "n", "", "Specify namespace of the cronjob trigger")
	updateCmd.Flags().StringP("schedule", "", "", "Specify schedule in cron format for scheduled function")
	updateCmd.Flags().StringP("function", "", "", "Name of the function to be associated with trigger")
	updateCmd.Flags().Bool("dryrun", false, "Output JSON manifest of the function without creating it")
	updateCmd.Flags().StringP("output", "o", "yaml", "Output format")
	updateCmd.Flags().StringP("payload", "p", "", "Specify a stringified JSON data to pass to function upon execution")
	updateCmd.Flags().StringP("payload-from-file", "f", "", "Specify a payload file to use. It must be a JSON file")
}


================================================
FILE: cmd/kubeless/trigger/http/create.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package http

import (
	"fmt"
	httpApi "github.com/kubeless/http-trigger/pkg/apis/kubeless/v1beta1"
	httpUtils "github.com/kubeless/http-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var createCmd = &cobra.Command{
	Use:   "create <http_trigger_name> FLAG",
	Short: "Create a http trigger",
	Long:  `Create a http trigger`,
	Run: func(cmd *cobra.Command, args []string) {

		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - http trigger name")
		}
		triggerName := args[0]
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		path, err := cmd.Flags().GetString("path")
		if err != nil {
			logrus.Fatal(err)
		}

		functionName, err := cmd.Flags().GetString("function-name")
		if err != nil {
			logrus.Fatal(err)
		}

		dryrun, err := cmd.Flags().GetBool("dryrun")
		if err != nil {
			logrus.Fatal(err)
		}

		output, err := cmd.Flags().GetString("output")
		if err != nil {
			logrus.Fatal(err)
		}

		kubelessClient, err := kubelessUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		_, err = kubelessUtils.GetFunctionCustomResource(kubelessClient, functionName, ns)
		if err != nil {
			logrus.Fatalf("Unable to find Function %s in namespace %s. Error %s", functionName, ns, err)
		}

		httpTrigger := httpApi.HTTPTrigger{}
		httpTrigger.TypeMeta = metav1.TypeMeta{
			Kind:       "HTTPTrigger",
			APIVersion: "kubeless.io/v1beta1",
		}
		httpTrigger.ObjectMeta = metav1.ObjectMeta{
			Name:      triggerName,
			Namespace: ns,
		}
		httpTrigger.ObjectMeta.Labels = map[string]string{
			"created-by": "kubeless",
		}
		httpTrigger.Spec.FunctionName = functionName

		if len(path) != 0 {
			httpTrigger.Spec.Path = path
		}

		enableTLSAcme, err := cmd.Flags().GetBool("enableTLSAcme")
		if err != nil {
			logrus.Fatal(err)
		}
		httpTrigger.Spec.TLSAcme = enableTLSAcme

		corsEnabled, err := cmd.Flags().GetBool("cors-enable")
		if err != nil {
			logrus.Fatal(err)
		}
		httpTrigger.Spec.CorsEnable = corsEnabled

		tlsSecret, err := cmd.Flags().GetString("tls-secret")
		if err != nil {
			logrus.Fatal(err)
		}
		if enableTLSAcme && len(tlsSecret) > 0 {
			logrus.Fatalf("Cannot specify both --enableTLSAcme and --tls-secret")
		}
		httpTrigger.Spec.TLSSecret = tlsSecret

		gateway, err := cmd.Flags().GetString("gateway")
		if err != nil {
			logrus.Fatal(err)
		}
		if gateway != "nginx" && gateway != "traefik" && gateway != "kong" {
			logrus.Fatalf("Unsupported gateway %s", gateway)
		}
		httpTrigger.Spec.Gateway = gateway

		hostName, err := cmd.Flags().GetString("hostname")
		if err != nil {
			logrus.Fatal(err)
		}
		if hostName == "" && gateway == "nginx" {
			// We assume that Nginx will be listening in the port 80
			// of the cluster plublic IP
			config, err := kubelessUtils.BuildOutOfClusterConfig()
			if err != nil {
				logrus.Fatal(err)
			}
			hostName, err = httpUtils.GetLocalHostname(config, functionName)
			if err != nil {
				logrus.Fatal(err)
			}
		}
		if hostName == "" {
			logrus.Fatalf("The --hostname flag is required")
		}
		httpTrigger.Spec.HostName = hostName

		basicAuthSecret, err := cmd.Flags().GetString("basic-auth-secret")
		if err != nil {
			logrus.Fatal(err)
		}
		httpTrigger.Spec.BasicAuthSecret = basicAuthSecret

		if dryrun == true {
			res, err := kubelessUtils.DryRunFmt(output, httpTrigger)
			if err != nil {
				logrus.Fatal(err)
			}
			fmt.Println(res)
			return
		}

		httpClient, err := httpUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		err = httpUtils.CreateHTTPTriggerCustomResource(httpClient, &httpTrigger)
		if err != nil {
			logrus.Fatalf("Failed to deploy HTTP trigger %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("HTTP trigger %s created in namespace %s successfully!", triggerName, ns)
	},
}

func init() {
	createCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the HTTP trigger")
	createCmd.Flags().StringP("function-name", "", "", "Name of the function to be associated with trigger")
	createCmd.Flags().StringP("path", "", "", "Ingress path for the function")
	createCmd.Flags().StringP("hostname", "", "", "Specify a valid hostname for the function")
	createCmd.Flags().BoolP("enableTLSAcme", "", false, "If true, routing rule will be configured for use with kube-lego")
	createCmd.Flags().StringP("gateway", "", "nginx", "Specify a valid gateway for the Ingress. Supported: nginx, traefik, kong")
	createCmd.Flags().StringP("basic-auth-secret", "", "", "Specify an existing secret name for basic authentication")
	createCmd.Flags().StringP("tls-secret", "", "", "Specify an existing secret that contains a TLS private key and certificate to secure ingress")
	createCmd.Flags().Bool("dryrun", false, "Output JSON manifest of the function without creating it")
	createCmd.Flags().StringP("output", "o", "yaml", "Output format")
	createCmd.Flags().BoolP("cors-enable", "", false, "If true then cors will be enabled on Http Trigger")
	createCmd.MarkFlagRequired("function-name")
}


================================================
FILE: cmd/kubeless/trigger/http/delete.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package http

import (
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	httpUtils "github.com/kubeless/http-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
)

var deleteCmd = &cobra.Command{

	Use:   "delete <http_trigger_name>",
	Short: "Delete a HTTP trigger",
	Long:  `Delete a HTTP trigger`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - Kafka trigger name")
		}
		triggerName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		httpClient, err := httpUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		err = httpUtils.DeleteHTTPTriggerCustomResource(httpClient, triggerName, ns)
		if err != nil {
			logrus.Fatalf("Failed to delete HTTP trigger object %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("HTTP trigger %s deleted from namespace %s successfully!", triggerName, ns)
	},
}

func init() {
	deleteCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
}


================================================
FILE: cmd/kubeless/trigger/http/http_trigger.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package http

import (
	"github.com/spf13/cobra"
)

// HTTPTriggerCmd command for http trigger commands
var HTTPTriggerCmd = &cobra.Command{
	Use:   "http SUBCOMMAND",
	Short: "http trigger specific operations",
	Long:  `http trigger command allows user to create, list, update, delete http triggers running on Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cmd.Help()
	},
}

func init() {
	HTTPTriggerCmd.AddCommand(createCmd)
	HTTPTriggerCmd.AddCommand(deleteCmd)
	HTTPTriggerCmd.AddCommand(listCmd)
	HTTPTriggerCmd.AddCommand(updateCmd)
}


================================================
FILE: cmd/kubeless/trigger/http/list.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package http

import (
	"fmt"
	"io"

	"github.com/gosuri/uitable"
	"github.com/kubeless/http-trigger/pkg/client/clientset/versioned"
	httpUtils "github.com/kubeless/http-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var listCmd = &cobra.Command{
	Use:     "list FLAG",
	Aliases: []string{"ls"},
	Short:   "list all HTTP triggers deployed to Kubeless",
	Long:    `list all HTTP triggers deployed to Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err.Error())
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		httpClient, err := httpUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		if err := doList(cmd.OutOrStdout(), httpClient, ns); err != nil {
			logrus.Fatal(err.Error())
		}
	},
}

func init() {
	listCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the function")
}

func doList(w io.Writer, kubelessClient versioned.Interface, ns string) error {
	triggersList, err := kubelessClient.KubelessV1beta1().HTTPTriggers(ns).List(metav1.ListOptions{})
	if err != nil {
		return err
	}
	table := uitable.New()
	table.MaxColWidth = 50
	table.Wrap = true
	table.AddRow("NAME", "NAMESPACE", "FUNCTION NAME")
	for _, trigger := range triggersList.Items {
		table.AddRow(trigger.Name, trigger.Namespace, trigger.Spec.FunctionName)
	}
	fmt.Fprintln(w, table)
	return nil
}


================================================
FILE: cmd/kubeless/trigger/http/update.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package http

import (
	"fmt"

	httpUtils "github.com/kubeless/http-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
)

var updateCmd = &cobra.Command{
	Use:   "update <http_trigger_name> FLAG",
	Short: "Update a http trigger",
	Long:  `Update a http trigger`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - http trigger name")
		}
		triggerName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		kubelessClient, err := kubelessUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		httpClient, err := httpUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}

		httpTrigger, err := httpUtils.GetHTTPTriggerCustomResource(httpClient, triggerName, ns)
		if err != nil {
			logrus.Fatalf("Unable to find HTTP trigger %s in namespace %s. Error %s", triggerName, ns, err)
		}

		functionName, err := cmd.Flags().GetString("function-name")
		if err != nil {
			logrus.Fatal(err)
		}

		if functionName != "" {
			_, err = kubelessUtils.GetFunctionCustomResource(kubelessClient, functionName, ns)
			if err != nil {
				logrus.Fatalf("Unable to find Function %s in namespace %s. Error %s", functionName, ns, err)
			}
			httpTrigger.Spec.FunctionName = functionName
		}

		path, err := cmd.Flags().GetString("path")
		if err != nil {
			logrus.Fatal(err)
		}
		if path != "" {
			httpTrigger.Spec.Path = path
		}

		hostName, err := cmd.Flags().GetString("hostname")
		if err != nil {
			logrus.Fatal(err)
		}
		if hostName != "" {
			httpTrigger.Spec.HostName = hostName
		}
		enableTLSAcme, err := cmd.Flags().GetBool("enableTLSAcme")
		if err != nil {
			logrus.Fatal(err)
		}
		httpTrigger.Spec.TLSAcme = enableTLSAcme

		tlsSecret, err := cmd.Flags().GetString("tls-secret")
		if err != nil {
			logrus.Fatal(err)
		}
		if enableTLSAcme && len(tlsSecret) > 0 {
			logrus.Fatalf("Cannot specify both --enableTLSAcme and --tls-secret")
		}
		if tlsSecret != "" {
			httpTrigger.Spec.TLSSecret = tlsSecret
		}

		gateway, err := cmd.Flags().GetString("gateway")
		if err != nil {
			logrus.Fatal(err)
		}
		if gateway != "" {
			httpTrigger.Spec.Gateway = gateway
		}

		basicAuthSecret, err := cmd.Flags().GetString("basic-auth-secret")
		if err != nil {
			logrus.Fatal(err)
		}
		if basicAuthSecret != "" {
			httpTrigger.Spec.BasicAuthSecret = basicAuthSecret
		}

		dryrun, err := cmd.Flags().GetBool("dryrun")
		if err != nil {
			logrus.Fatal(err)
		}

		output, err := cmd.Flags().GetString("output")
		if err != nil {
			logrus.Fatal(err)
		}

		if dryrun == true {
			res, err := kubelessUtils.DryRunFmt(output, httpTrigger)
			if err != nil {
				logrus.Fatal(err)
			}
			fmt.Println(res)
			return
		}

		err = httpUtils.UpdateHTTPTriggerCustomResource(httpClient, httpTrigger)
		if err != nil {
			logrus.Fatalf("Failed to deploy HTTP trigger %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("HTTP trigger %s updated in namespace %s successfully!", triggerName, ns)
	},
}

func init() {
	updateCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the HTTP trigger")
	updateCmd.Flags().StringP("function-name", "", "", "Name of the function to be associated with trigger")
	updateCmd.Flags().StringP("path", "", "", "Ingress path for the function")
	updateCmd.Flags().StringP("hostname", "", "", "Specify a valid hostname for the function")
	updateCmd.Flags().BoolP("enableTLSAcme", "", false, "If true, routing rule will be configured for use with kube-lego")
	updateCmd.Flags().StringP("gateway", "", "", "Specify a valid gateway for the Ingress")
	updateCmd.Flags().StringP("basic-auth-secret", "", "", "Specify an existing secret name for basic authentication")
	updateCmd.Flags().StringP("tls-secret", "", "", "Specify an existing secret that contains a TLS private key and certificate to secure ingress")
	updateCmd.Flags().Bool("dryrun", false, "Output JSON manifest of the function without creating it")
	updateCmd.Flags().StringP("output", "o", "yaml", "Output format")
}


================================================
FILE: cmd/kubeless/trigger/kafka/create.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package kafka

import (
	"fmt"

	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	kafkaApi "github.com/kubeless/kafka-trigger/pkg/apis/kubeless/v1beta1"
	kafkaUtils "github.com/kubeless/kafka-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

var createCmd = &cobra.Command{

	Use:   "create <kafka_trigger_name> FLAG",
	Short: "Create a Kafka trigger",
	Long:  `Create a Kafka trigger`,
	Run: func(cmd *cobra.Command, args []string) {

		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - kafka trigger name")
		}
		triggerName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		topic, err := cmd.Flags().GetString("trigger-topic")
		if err != nil {
			logrus.Fatal(err)
		}

		functionSelector, err := cmd.Flags().GetString("function-selector")
		if err != nil {
			logrus.Fatal(err)
		}

		dryrun, err := cmd.Flags().GetBool("dryrun")
		if err != nil {
			logrus.Fatal(err)
		}

		output, err := cmd.Flags().GetString("output")
		if err != nil {
			logrus.Fatal(err)
		}

		labelSelector, err := metav1.ParseToLabelSelector(functionSelector)
		if err != nil {
			logrus.Fatal("Invalid lable selector specified " + err.Error())
		}

		kafkaTrigger := kafkaApi.KafkaTrigger{}
		kafkaTrigger.TypeMeta = metav1.TypeMeta{
			Kind:       "KafkaTrigger",
			APIVersion: "kubeless.io/v1beta1",
		}
		kafkaTrigger.ObjectMeta = metav1.ObjectMeta{
			Name:      triggerName,
			Namespace: ns,
		}
		kafkaTrigger.ObjectMeta.Labels = map[string]string{
			"created-by": "kubeless",
		}
		kafkaTrigger.Spec.FunctionSelector.MatchLabels = labelSelector.MatchLabels
		kafkaTrigger.Spec.Topic = topic

		if dryrun == true {
			res, err := kubelessUtils.DryRunFmt(output, kafkaTrigger)
			if err != nil {
				logrus.Fatal(err)
			}
			fmt.Println(res)
			return
		}

		kafkaClient, err := kafkaUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}
		err = kafkaUtils.CreateKafkaTriggerCustomResource(kafkaClient, &kafkaTrigger)
		if err != nil {
			logrus.Fatalf("Failed to create Kafka trigger object %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("Kafka trigger %s created in namespace %s successfully!", triggerName, ns)

	},
}

func init() {
	createCmd.Flags().StringP("namespace", "n", "", "Specify namespace for the kafka trigger")
	createCmd.Flags().StringP("trigger-topic", "", "", "Specify topic to listen to in Kafka broker")
	createCmd.Flags().StringP("function-selector", "", "", "Selector (label query) to select function on (e.g. --function-selector key1=value1,key2=value2)")
	createCmd.MarkFlagRequired("trigger-topic")
	createCmd.MarkFlagRequired("function-selector")
	createCmd.Flags().Bool("dryrun", false, "Output JSON manifest of the function without creating it")
	createCmd.Flags().StringP("output", "o", "yaml", "Output format")
}


================================================
FILE: cmd/kubeless/trigger/kafka/delete.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package kafka

import (
	"github.com/sirupsen/logrus"
	"github.com/spf13/cobra"

	kafkaUtils "github.com/kubeless/kafka-trigger/pkg/utils"
	kubelessUtils "github.com/kubeless/kubeless/pkg/utils"
)

var deleteCmd = &cobra.Command{

	Use:   "delete <kafka_trigger_name>",
	Short: "Delete a Kafka trigger",
	Long:  `Delete a Kafka trigger`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 1 {
			logrus.Fatal("Need exactly one argument - Kafka trigger name")
		}
		triggerName := args[0]

		ns, err := cmd.Flags().GetString("namespace")
		if err != nil {
			logrus.Fatal(err)
		}
		if ns == "" {
			ns = kubelessUtils.GetDefaultNamespace()
		}

		kafkaClient, err := kafkaUtils.GetKubelessClientOutCluster()
		if err != nil {
			logrus.Fatalf("Can not create out-of-cluster client: %v", err)
		}
		err = kafkaUtils.DeleteKafkaTriggerCustomResource(kafkaClient, triggerName, ns)
		if err != nil {
			logrus.Fatalf("Failed to delete Kafka trigger object %s in namespace %s. Error: %s", triggerName, ns, err)
		}
		logrus.Infof("Kafka trigger %s deleted from namespace %s successfully!", triggerName, ns)
	},
}

func init() {
	deleteCmd.Flags().StringP("namespace", "n", "", "Specify namespace of the Kafka trigger")
}


================================================
FILE: cmd/kubeless/trigger/kafka/kafka_trigger.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

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.
*/

package kafka

import (
	"github.com/spf13/cobra"
)

// KafkaTriggerCmd command for Kafka trigger commands
var KafkaTriggerCmd = &cobra.Command{
	Use:   "kafka SUBCOMMAND",
	Short: "kafka trigger specific operations",
	Long:  `kafka trigger command allows user to create, list, update, delete kafka triggers running on Kubeless`,
	Run: func(cmd *cobra.Command, args []string) {
		cmd.Help()
	},
}

func init() {
	KafkaTriggerCmd.AddCommand(createCmd)
	KafkaTriggerCmd.AddCommand(deleteCmd)
	KafkaTriggerCmd.AddCommand(listCmd)
	KafkaTriggerCmd.AddCommand(updateCmd)
}


================================================
FILE: cmd/kubeless/trigger/kafka/list.go
================================================
/*
Copyright (c) 2016-2017 Bitnami

Licensed under the Apache License, Version 2.0 (the "License");
yo
Download .txt
gitextract_a4vhstu0/

├── .circleci/
│   └── config.yml
├── .github/
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── gcloud.json.enc
│   └── issue_template.md
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── OWNERS
├── README.md
├── cmd/
│   ├── function-controller/
│   │   └── function-controller.go
│   └── kubeless/
│       ├── autoscale/
│       │   ├── autoscale.go
│       │   ├── autoscaleCreate.go
│       │   ├── autoscaleDelete.go
│       │   ├── autoscaleList.go
│       │   ├── autoscaleList_test.go
│       │   └── autoscale_test.go
│       ├── completion/
│       │   └── completion.go
│       ├── function/
│       │   ├── call.go
│       │   ├── delete.go
│       │   ├── deploy.go
│       │   ├── describe.go
│       │   ├── function.go
│       │   ├── function_test.go
│       │   ├── list.go
│       │   ├── list_test.go
│       │   ├── logs.go
│       │   ├── top.go
│       │   ├── top_test.go
│       │   └── update.go
│       ├── getserverconfig/
│       │   └── getServerConfig.go
│       ├── kubeless.go
│       ├── topic/
│       │   ├── topic.go
│       │   ├── topicCreate.go
│       │   ├── topicDelete.go
│       │   ├── topicList.go
│       │   └── topicPublish.go
│       ├── trigger/
│       │   ├── cronjob/
│       │   │   ├── create.go
│       │   │   ├── cronjob_trigger.go
│       │   │   ├── delete.go
│       │   │   ├── list.go
│       │   │   └── update.go
│       │   ├── http/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── http_trigger.go
│       │   │   ├── list.go
│       │   │   └── update.go
│       │   ├── kafka/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── kafka_trigger.go
│       │   │   ├── list.go
│       │   │   └── update.go
│       │   ├── kinesis/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── kinesis_trigger.go
│       │   │   ├── list.go
│       │   │   ├── publish.go
│       │   │   ├── stream_create.go
│       │   │   └── update.go
│       │   ├── nats/
│       │   │   ├── create.go
│       │   │   ├── delete.go
│       │   │   ├── list.go
│       │   │   ├── nats_trigger.go
│       │   │   ├── publish.go
│       │   │   └── update.go
│       │   └── trigger.go
│       └── version/
│           └── version.go
├── docker/
│   ├── controller-manager
│   ├── dev-environment/
│   │   ├── Dockerfile
│   │   └── entry-point.sh
│   ├── event-sources/
│   │   └── kubernetes/
│   │       ├── Dockerfile
│   │       ├── README.md
│   │       └── events.py
│   ├── function-controller/
│   │   └── Dockerfile
│   ├── function-image-builder/
│   │   ├── Dockerfile
│   │   └── entrypoint.sh
│   ├── runtime/
│   │   └── README.md
│   └── unzip/
│       └── Dockerfile
├── docs/
│   ├── GKE-deployment.md
│   ├── README.md
│   ├── advanced-function-deployment.md
│   ├── architecture.md
│   ├── autoscaling.md
│   ├── building-functions.md
│   ├── cronjob-triggers.md
│   ├── debug-functions.md
│   ├── debugging.md
│   ├── dev-guide.md
│   ├── function-controller-configuration.md
│   ├── http-triggers.md
│   ├── implementing-new-runtime.md
│   ├── implementing-new-trigger.md
│   ├── kubeless-functions.md
│   ├── kubeless-on-AKS.md
│   ├── misc/
│   │   ├── kafka-pv-gke.yaml
│   │   ├── kubeless-grafana-dashboard.json
│   │   └── zookeeper-pv-gke.yaml
│   ├── monitoring.md
│   ├── proposals/
│   │   ├── decoupling-triggers-and-runtimes.md
│   │   └── http-triggers.md
│   ├── pubsub-functions.md
│   ├── quick-start.md
│   ├── release-flow.md
│   ├── runtimes.md
│   ├── streaming-functions.md
│   ├── triggers.md
│   ├── troubleshooting.md
│   └── use-existing-kafka.md
├── examples/
│   ├── Makefile
│   ├── README.md
│   ├── ballerina/
│   │   ├── hello_with_conf/
│   │   │   ├── hello_with_conf.bal
│   │   │   └── kubeless.toml
│   │   ├── helloget.bal
│   │   └── hellowithdata.bal
│   ├── dotnetcore/
│   │   ├── dependency-yaml.cs
│   │   ├── dependency-yaml.csproj
│   │   ├── fibonacci.cs
│   │   ├── fibonacci.csproj
│   │   ├── helloget.cs
│   │   ├── helloget.csproj
│   │   ├── hellowithdata.cs
│   │   └── hellowithdata.csproj
│   ├── golang/
│   │   ├── go.mod
│   │   ├── helloget.go
│   │   ├── hellowithdata.go
│   │   └── hellowithdeps.go
│   ├── java/
│   │   ├── HelloGet.java
│   │   ├── HelloWithData.java
│   │   ├── HelloWithDeps.java
│   │   └── pom.xml
│   ├── jvm/
│   │   ├── Readme.md
│   │   ├── java/
│   │   │   ├── Readme.md
│   │   │   ├── build/
│   │   │   │   └── libs/
│   │   │   │       └── java-0.1-all.jar
│   │   │   ├── build.gradle
│   │   │   ├── src/
│   │   │   │   └── main/
│   │   │   │       └── java/
│   │   │   │           └── io/
│   │   │   │               └── ino/
│   │   │   │                   └── Handler.java
│   │   │   └── test-java-jvm.jar
│   │   └── scala/
│   │       ├── Readme.md
│   │       ├── build.sbt
│   │       ├── project/
│   │       │   ├── assembly.sbt
│   │       │   └── build.properties
│   │       └── src/
│   │           └── main/
│   │               └── scala/
│   │                   └── de/
│   │                       └── inoio/
│   │                           └── Handler.scala
│   ├── nodejs/
│   │   ├── function.yaml
│   │   ├── function1.yaml
│   │   ├── helloFunctions.tar.bz2
│   │   ├── helloFunctions.tar.xz
│   │   ├── helloget.js
│   │   ├── hellostream.js
│   │   ├── hellowithdata.js
│   │   ├── hellowithdeps.js
│   │   ├── index.js
│   │   └── package.json
│   ├── php/
│   │   ├── composer.json
│   │   ├── helloget.php
│   │   ├── hellowithdata.php
│   │   └── hellowithdeps.php
│   ├── python/
│   │   ├── Dockerfile
│   │   ├── function.yaml
│   │   ├── function1.yaml
│   │   ├── helloget.py
│   │   ├── hellowithdata.py
│   │   ├── hellowithdeps.py
│   │   ├── hellowithdepshelper.py
│   │   └── requirements.txt
│   └── ruby/
│       ├── Gemfile
│       ├── function.yaml
│       ├── helloget.rb
│       ├── hellowithdata.rb
│       ├── hellowithdeps.rb
│       └── latest.rb
├── go.mod
├── go.sum
├── hack/
│   ├── boilerplate.go.txt
│   └── update-codegen.sh
├── kubeless-non-rbac.jsonnet
├── kubeless-openshift.jsonnet
├── kubeless.jsonnet
├── manifests/
│   ├── README.md
│   ├── autoscaling/
│   │   ├── custom-metrics.yaml
│   │   ├── prometheus-operator.yaml
│   │   ├── sample-metrics-app.yaml
│   │   └── sample-prometheus-instance.yaml
│   ├── kinesis/
│   │   └── kinesalite.yaml
│   ├── monitoring/
│   │   ├── grafana-configmap.yaml
│   │   ├── grafana-deployment.yaml
│   │   ├── grafana-job.yaml
│   │   ├── grafana-service.yaml
│   │   └── prometheus.yaml
│   ├── nats/
│   │   └── nats-cluster.yaml
│   └── ui/
│       └── README.md
├── pkg/
│   ├── apis/
│   │   └── kubeless/
│   │       ├── register.go
│   │       └── v1beta1/
│   │           ├── doc.go
│   │           ├── function.go
│   │           ├── register.go
│   │           └── zz_generated.deepcopy.go
│   ├── client/
│   │   ├── clientset/
│   │   │   └── versioned/
│   │   │       ├── clientset.go
│   │   │       ├── doc.go
│   │   │       ├── fake/
│   │   │       │   ├── clientset_generated.go
│   │   │       │   ├── doc.go
│   │   │       │   └── register.go
│   │   │       ├── scheme/
│   │   │       │   ├── doc.go
│   │   │       │   └── register.go
│   │   │       └── typed/
│   │   │           └── kubeless/
│   │   │               └── v1beta1/
│   │   │                   ├── doc.go
│   │   │                   ├── fake/
│   │   │                   │   ├── doc.go
│   │   │                   │   ├── fake_function.go
│   │   │                   │   └── fake_kubeless_client.go
│   │   │                   ├── function.go
│   │   │                   ├── generated_expansion.go
│   │   │                   └── kubeless_client.go
│   │   ├── informers/
│   │   │   └── externalversions/
│   │   │       ├── factory.go
│   │   │       ├── generic.go
│   │   │       ├── internalinterfaces/
│   │   │       │   └── factory_interfaces.go
│   │   │       └── kubeless/
│   │   │           ├── interface.go
│   │   │           └── v1beta1/
│   │   │               ├── function.go
│   │   │               └── interface.go
│   │   └── listers/
│   │       └── kubeless/
│   │           └── v1beta1/
│   │               ├── expansion_generated.go
│   │               └── function.go
│   ├── controller/
│   │   ├── function_controller.go
│   │   └── function_controller_test.go
│   ├── function-image-builder/
│   │   ├── image_builder.go
│   │   └── layer-builder/
│   │       ├── description.go
│   │       ├── description_test.go
│   │       ├── layer.go
│   │       ├── layer_builder.go
│   │       ├── layer_test.go
│   │       ├── manifest.go
│   │       └── manifest_test.go
│   ├── function-proxy/
│   │   ├── Gopkg.toml
│   │   ├── proxy.go
│   │   └── utils/
│   │       └── proxy-utils.go
│   ├── functions/
│   │   └── params.go
│   ├── langruntime/
│   │   ├── langruntime.go
│   │   ├── langruntime_test.go
│   │   └── langruntimetestutils.go
│   ├── registry/
│   │   ├── registry.go
│   │   └── registry_test.go
│   ├── utils/
│   │   ├── configlocation.go
│   │   ├── exec.go
│   │   ├── exec_test.go
│   │   ├── k8sutil.go
│   │   ├── k8sutil_test.go
│   │   ├── kubelessutil.go
│   │   ├── kubelessutil_test.go
│   │   └── metrics.go
│   └── version/
│       └── version.go
├── script/
│   ├── .validate
│   ├── binary
│   ├── binary-cli
│   ├── binary-controller
│   ├── cluster-up-minikube.sh
│   ├── create_release.sh
│   ├── enable-gcloud.sh
│   ├── find_digest.sh
│   ├── integration-tests
│   ├── libtest.bash
│   ├── pull-or-build-image.sh
│   ├── release_utils.sh
│   ├── start-gke-env.sh
│   ├── start-test-environment.sh
│   ├── upload_release_notes.sh
│   ├── validate-git-marks
│   ├── validate-gofmt
│   ├── validate-lint
│   ├── validate-test
│   └── validate-vet
└── tests/
    ├── deployment-tests.bats
    ├── integration-tests-cronjob.bats
    ├── integration-tests-http.bats
    ├── integration-tests-kafka.bats
    ├── integration-tests-kinesis.bats
    ├── integration-tests-nats.bats
    ├── integration-tests-prebuilt.bats
    └── integration-tests.bats
Download .txt
SYMBOL INDEX (485 symbols across 123 files)

FILE: cmd/function-controller/function-controller.go
  constant globalUsage (line 37) | globalUsage = ``
  function main (line 79) | func main() {

FILE: cmd/kubeless/autoscale/autoscale.go
  function init (line 37) | func init() {
  function getHorizontalAutoscaleDefinition (line 47) | func getHorizontalAutoscaleDefinition(name, ns, metric string, min, max ...

FILE: cmd/kubeless/autoscale/autoscaleCreate.go
  function init (line 77) | func init() {

FILE: cmd/kubeless/autoscale/autoscaleList.go
  function init (line 57) | func init() {
  function doAutoscaleList (line 61) | func doAutoscaleList(w io.Writer, client kubernetes.Interface, ns, outpu...
  function printAutoscale (line 73) | func printAutoscale(w io.Writer, ass []v2beta1.HorizontalPodAutoscaler, ...

FILE: cmd/kubeless/autoscale/autoscaleList_test.go
  function listAutoscaleOutput (line 16) | func listAutoscaleOutput(t *testing.T, client kubernetes.Interface, ns, ...
  function TestAutoscaleList (line 26) | func TestAutoscaleList(t *testing.T) {

FILE: cmd/kubeless/autoscale/autoscale_test.go
  function TestGetHorizontalAutoscaleDefinition (line 11) | func TestGetHorizontalAutoscaleDefinition(t *testing.T) {

FILE: cmd/kubeless/function/call.go
  function init (line 117) | func init() {

FILE: cmd/kubeless/function/delete.go
  function init (line 55) | func init() {

FILE: cmd/kubeless/function/deploy.go
  function init (line 284) | func init() {

FILE: cmd/kubeless/function/describe.go
  function init (line 67) | func init() {
  function print (line 72) | func print(f kubelessApi.Function, name, output string) error {

FILE: cmd/kubeless/function/function.go
  function init (line 44) | func init() {
  function getKV (line 55) | func getKV(input string) (string, string) {
  function parseLabel (line 69) | func parseLabel(labels []string) map[string]string {
  function parseEnv (line 78) | func parseEnv(envs []string) []v1.EnvVar {
  function parseResource (line 90) | func parseResource(in string) (resource.Quantity, error) {
  function parseNodeSelectors (line 103) | func parseNodeSelectors(nodeSelectors []string) map[string]string {
  function getFunctionDescription (line 112) | func getFunctionDescription(funcName, ns, handler, file, deps, runtime, ...
  function getDeploymentStatus (line 269) | func getDeploymentStatus(cli kubernetes.Interface, funcName, ns string) ...
  function getFunctions (line 283) | func getFunctions(kubelessClient versioned.Interface, namespace, functio...

FILE: cmd/kubeless/function/function_test.go
  function TestParseLabel (line 43) | func TestParseLabel(t *testing.T) {
  function TestParseEnv (line 60) | func TestParseEnv(t *testing.T) {
  function TestParseNodeSelectors (line 96) | func TestParseNodeSelectors(t *testing.T) {
  function TestGetFunctionDescription (line 111) | func TestGetFunctionDescription(t *testing.T) {
  function getSha256 (line 595) | func getSha256(bytes []byte) (string, error) {

FILE: cmd/kubeless/function/list.go
  function init (line 70) | func init() {
  function doList (line 75) | func doList(w io.Writer, kubelessClient versioned.Interface, apiV1Client...
  function parseDeps (line 97) | func parseDeps(deps, runtime string) (res string, err error) {
  function printFunctions (line 120) | func printFunctions(w io.Writer, functions []*kubelessApi.Function, cli ...

FILE: cmd/kubeless/function/list_test.go
  function listOutput (line 37) | func listOutput(t *testing.T, client versioned.Interface, apiV1Client ku...
  function TestList (line 47) | func TestList(t *testing.T) {

FILE: cmd/kubeless/function/logs.go
  function init (line 77) | func init() {

FILE: cmd/kubeless/function/top.go
  function init (line 70) | func init() {
  function doTop (line 76) | func doTop(w io.Writer, kubelessClient versioned.Interface, apiV1Client ...
  function printTop (line 110) | func printTop(w io.Writer, metrics []*utils.Metric, cli kubernetes.Inter...

FILE: cmd/kubeless/function/top_test.go
  type testMetricsHandler (line 41) | type testMetricsHandler struct
    method GetRawMetrics (line 45) | func (h *testMetricsHandler) GetRawMetrics(apiClient kubernetes.Interf...
  function topOutput (line 58) | func topOutput(t *testing.T, client versioned.Interface, apiV1Client kub...
  function TestTop (line 68) | func TestTop(t *testing.T) {

FILE: cmd/kubeless/function/update.go
  function init (line 225) | func init() {

FILE: cmd/kubeless/kubeless.go
  function newRootCmd (line 35) | func newRootCmd() *cobra.Command {
  function main (line 46) | func main() {

FILE: cmd/kubeless/topic/topic.go
  function init (line 33) | func init() {

FILE: cmd/kubeless/topic/topicCreate.go
  function createTopic (line 59) | func createTopic(conf *rest.Config, clientset kubernetes.Interface, ctlN...
  function execCommand (line 73) | func execCommand(conf *rest.Config, k8sClientSet kubernetes.Interface, c...

FILE: cmd/kubeless/topic/topicDelete.go
  function deleteTopic (line 58) | func deleteTopic(conf *rest.Config, clientset kubernetes.Interface, ctlN...

FILE: cmd/kubeless/topic/topicList.go
  function listTopic (line 54) | func listTopic(conf *rest.Config, clientset kubernetes.Interface, ctlNam...

FILE: cmd/kubeless/topic/topicPublish.go
  function publishTopic (line 65) | func publishTopic(conf *rest.Config, clientset kubernetes.Interface, nam...
  function init (line 116) | func init() {

FILE: cmd/kubeless/trigger/cronjob/create.go
  function init (line 143) | func init() {

FILE: cmd/kubeless/trigger/cronjob/cronjob_trigger.go
  function init (line 38) | func init() {
  function parsePayload (line 45) | func parsePayload(content string, file string) (interface{}, error) {
  function getPayloadRawContent (line 58) | func getPayloadRawContent(file string) (string, error) {
  function parsePayloadContent (line 77) | func parsePayloadContent(raw string) interface{} {

FILE: cmd/kubeless/trigger/cronjob/delete.go
  function init (line 58) | func init() {

FILE: cmd/kubeless/trigger/cronjob/list.go
  function init (line 57) | func init() {
  function doList (line 61) | func doList(w io.Writer, kubelessClient versioned.Interface, ns string) ...

FILE: cmd/kubeless/trigger/cronjob/update.go
  function init (line 135) | func init() {

FILE: cmd/kubeless/trigger/http/create.go
  function init (line 175) | func init() {

FILE: cmd/kubeless/trigger/http/delete.go
  function init (line 59) | func init() {

FILE: cmd/kubeless/trigger/http/http_trigger.go
  function init (line 33) | func init() {

FILE: cmd/kubeless/trigger/http/list.go
  function init (line 57) | func init() {
  function doList (line 61) | func doList(w io.Writer, kubelessClient versioned.Interface, ns string) ...

FILE: cmd/kubeless/trigger/http/update.go
  function init (line 149) | func init() {

FILE: cmd/kubeless/trigger/kafka/create.go
  function init (line 113) | func init() {

FILE: cmd/kubeless/trigger/kafka/delete.go
  function init (line 58) | func init() {

FILE: cmd/kubeless/trigger/kafka/kafka_trigger.go
  function init (line 33) | func init() {

FILE: cmd/kubeless/trigger/kafka/list.go
  function init (line 59) | func init() {
  function doList (line 63) | func doList(w io.Writer, kubelessClient versioned.Interface, ns string) ...

FILE: cmd/kubeless/trigger/kafka/update.go
  function init (line 107) | func init() {

FILE: cmd/kubeless/trigger/kinesis/create.go
  function init (line 153) | func init() {

FILE: cmd/kubeless/trigger/kinesis/delete.go
  function init (line 59) | func init() {

FILE: cmd/kubeless/trigger/kinesis/kinesis_trigger.go
  function init (line 33) | func init() {

FILE: cmd/kubeless/trigger/kinesis/list.go
  function init (line 59) | func init() {
  function doList (line 63) | func doList(w io.Writer, kubelessClient versioned.Interface, ns string) ...

FILE: cmd/kubeless/trigger/kinesis/publish.go
  function init (line 117) | func init() {

FILE: cmd/kubeless/trigger/kinesis/stream_create.go
  function init (line 99) | func init() {

FILE: cmd/kubeless/trigger/kinesis/update.go
  function init (line 130) | func init() {

FILE: cmd/kubeless/trigger/nats/create.go
  function init (line 114) | func init() {

FILE: cmd/kubeless/trigger/nats/delete.go
  function init (line 59) | func init() {

FILE: cmd/kubeless/trigger/nats/list.go
  function init (line 59) | func init() {
  function doList (line 63) | func doList(w io.Writer, kubelessClient versioned.Interface, ns string) ...

FILE: cmd/kubeless/trigger/nats/nats_trigger.go
  function init (line 33) | func init() {

FILE: cmd/kubeless/trigger/nats/publish.go
  function publishTopic (line 53) | func publishTopic(topic, message, url string) error {
  function init (line 68) | func init() {

FILE: cmd/kubeless/trigger/nats/update.go
  function init (line 107) | func init() {

FILE: cmd/kubeless/trigger/trigger.go
  function init (line 38) | func init() {

FILE: docker/event-sources/kubernetes/events.py
  function pods (line 29) | def pods():
  function namespaces (line 39) | def namespaces():
  function services (line 49) | def services():
  function deployments (line 60) | def deployments():
  function replicasets (line 70) | def replicasets():

FILE: examples/dotnetcore/dependency-yaml.cs
  class module (line 5) | public class module
    method handler (line 7) | public string handler(Event k8Event, Context k8Context)
  class Person (line 20) | public class Person

FILE: examples/dotnetcore/fibonacci.cs
  class module (line 4) | public class module
    method handler (line 6) | public int handler(Event k8Event, Context k8Context)
    method fibonacci (line 13) | public int fibonacci(int n)

FILE: examples/dotnetcore/helloget.cs
  class module (line 4) | public class module
    method handler (line 6) | public string handler(Event k8Event, Context k8Context)

FILE: examples/dotnetcore/hellowithdata.cs
  class module (line 4) | public class module
    method handler (line 6) | public object handler(Event k8Event, Context k8Context)

FILE: examples/golang/helloget.go
  function Foo (line 8) | func Foo(event functions.Event, context functions.Context) (string, erro...

FILE: examples/golang/hellowithdata.go
  function Handler (line 10) | func Handler(event functions.Event, context functions.Context) (string, ...

FILE: examples/golang/hellowithdeps.go
  function Hello (line 9) | func Hello(event functions.Event, context functions.Context) (string, er...

FILE: examples/java/HelloGet.java
  class Foo (line 6) | public class Foo {
    method foo (line 7) | public String foo(io.kubeless.Event event, io.kubeless.Context context) {

FILE: examples/java/HelloWithData.java
  class Foo (line 6) | public class Foo {
    method foo (line 7) | public String foo(io.kubeless.Event event, io.kubeless.Context context) {

FILE: examples/java/HelloWithDeps.java
  class Hello (line 8) | public class Hello {
    method sayHello (line 9) | public String sayHello(io.kubeless.Event event, io.kubeless.Context co...

FILE: examples/jvm/java/src/main/java/io/ino/Handler.java
  class Handler (line 3) | public class Handler {
    method sayHello (line 4) | public String sayHello(io.kubeless.Event event, io.kubeless.Context co...

FILE: examples/nodejs/hellostream.js
  function fromString (line 4) | function fromString(string) {

FILE: examples/php/helloget.php
  function foo (line 3) | function foo($event, $context) {

FILE: examples/php/hellowithdata.php
  function foo (line 3) | function foo($event, $context) {

FILE: examples/php/hellowithdeps.php
  function foo (line 8) | function foo($event, $context) {

FILE: examples/python/helloget.py
  function foo (line 1) | def foo(event, context):

FILE: examples/python/hellowithdata.py
  function handler (line 1) | def handler(event, context):

FILE: examples/python/hellowithdepshelper.py
  function foo (line 4) | def foo(event, context):

FILE: examples/ruby/helloget.rb
  function foo (line 1) | def foo(event, context)

FILE: examples/ruby/hellowithdata.rb
  function handler (line 1) | def handler(event, context)

FILE: examples/ruby/hellowithdeps.rb
  function foo (line 3) | def foo(event, context)

FILE: examples/ruby/latest.rb
  function handler (line 2) | def handler(event, context)

FILE: pkg/apis/kubeless/register.go
  constant GroupName (line 5) | GroupName = "kubeless.io"

FILE: pkg/apis/kubeless/v1beta1/function.go
  type Function (line 30) | type Function struct
  type FunctionSpec (line 37) | type FunctionSpec struct
  type FunctionList (line 53) | type FunctionList struct

FILE: pkg/apis/kubeless/v1beta1/register.go
  function Kind (line 15) | func Kind(kind string) schema.GroupKind {
  function Resource (line 20) | func Resource(resource string) schema.GroupResource {
  function addKnownTypes (line 33) | func addKnownTypes(scheme *runtime.Scheme) error {

FILE: pkg/apis/kubeless/v1beta1/zz_generated.deepcopy.go
  method DeepCopyInto (line 28) | func (in *Function) DeepCopyInto(out *Function) {
  method DeepCopy (line 37) | func (in *Function) DeepCopy() *Function {
  method DeepCopyObject (line 47) | func (in *Function) DeepCopyObject() runtime.Object {
  method DeepCopyInto (line 55) | func (in *FunctionList) DeepCopyInto(out *FunctionList) {
  method DeepCopy (line 75) | func (in *FunctionList) DeepCopy() *FunctionList {
  method DeepCopyObject (line 85) | func (in *FunctionList) DeepCopyObject() runtime.Object {
  method DeepCopyInto (line 93) | func (in *FunctionSpec) DeepCopyInto(out *FunctionSpec) {
  method DeepCopy (line 102) | func (in *FunctionSpec) DeepCopy() *FunctionSpec {

FILE: pkg/client/clientset/versioned/clientset.go
  type Interface (line 26) | type Interface interface
  type Clientset (line 35) | type Clientset struct
    method KubelessV1beta1 (line 41) | func (c *Clientset) KubelessV1beta1() kubelessv1beta1.KubelessV1beta1I...
    method Kubeless (line 47) | func (c *Clientset) Kubeless() kubelessv1beta1.KubelessV1beta1Interface {
    method Discovery (line 52) | func (c *Clientset) Discovery() discovery.DiscoveryInterface {
  function NewForConfig (line 60) | func NewForConfig(c *rest.Config) (*Clientset, error) {
  function NewForConfigOrDie (line 82) | func NewForConfigOrDie(c *rest.Config) *Clientset {
  function New (line 91) | func New(c rest.Interface) *Clientset {

FILE: pkg/client/clientset/versioned/fake/clientset_generated.go
  function NewSimpleClientset (line 33) | func NewSimpleClientset(objects ...runtime.Object) *Clientset {
  type Clientset (line 51) | type Clientset struct
    method Discovery (line 56) | func (c *Clientset) Discovery() discovery.DiscoveryInterface {
    method KubelessV1beta1 (line 63) | func (c *Clientset) KubelessV1beta1() kubelessv1beta1.KubelessV1beta1I...
    method Kubeless (line 68) | func (c *Clientset) Kubeless() kubelessv1beta1.KubelessV1beta1Interface {

FILE: pkg/client/clientset/versioned/fake/register.go
  function init (line 30) | func init() {
  function AddToScheme (line 49) | func AddToScheme(scheme *runtime.Scheme) {

FILE: pkg/client/clientset/versioned/scheme/register.go
  function init (line 30) | func init() {
  function AddToScheme (line 49) | func AddToScheme(scheme *runtime.Scheme) {

FILE: pkg/client/clientset/versioned/typed/kubeless/v1beta1/fake/fake_function.go
  type FakeFunctions (line 29) | type FakeFunctions struct
    method Get (line 39) | func (c *FakeFunctions) Get(name string, options v1.GetOptions) (resul...
    method List (line 50) | func (c *FakeFunctions) List(opts v1.ListOptions) (result *v1beta1.Fun...
    method Watch (line 72) | func (c *FakeFunctions) Watch(opts v1.ListOptions) (watch.Interface, e...
    method Create (line 79) | func (c *FakeFunctions) Create(function *v1beta1.Function) (result *v1...
    method Update (line 90) | func (c *FakeFunctions) Update(function *v1beta1.Function) (result *v1...
    method Delete (line 101) | func (c *FakeFunctions) Delete(name string, options *v1.DeleteOptions)...
    method DeleteCollection (line 109) | func (c *FakeFunctions) DeleteCollection(options *v1.DeleteOptions, li...
    method Patch (line 117) | func (c *FakeFunctions) Patch(name string, pt types.PatchType, data []...

FILE: pkg/client/clientset/versioned/typed/kubeless/v1beta1/fake/fake_kubeless_client.go
  type FakeKubelessV1beta1 (line 24) | type FakeKubelessV1beta1 struct
    method Functions (line 28) | func (c *FakeKubelessV1beta1) Functions(namespace string) v1beta1.Func...
    method RESTClient (line 34) | func (c *FakeKubelessV1beta1) RESTClient() rest.Interface {

FILE: pkg/client/clientset/versioned/typed/kubeless/v1beta1/function.go
  type FunctionsGetter (line 29) | type FunctionsGetter interface
  type FunctionInterface (line 34) | type FunctionInterface interface
  type functions (line 47) | type functions struct
    method Get (line 61) | func (c *functions) Get(name string, options v1.GetOptions) (result *v...
    method List (line 74) | func (c *functions) List(opts v1.ListOptions) (result *v1beta1.Functio...
    method Watch (line 86) | func (c *functions) Watch(opts v1.ListOptions) (watch.Interface, error) {
    method Create (line 96) | func (c *functions) Create(function *v1beta1.Function) (result *v1beta...
    method Update (line 108) | func (c *functions) Update(function *v1beta1.Function) (result *v1beta...
    method Delete (line 121) | func (c *functions) Delete(name string, options *v1.DeleteOptions) err...
    method DeleteCollection (line 132) | func (c *functions) DeleteCollection(options *v1.DeleteOptions, listOp...
    method Patch (line 143) | func (c *functions) Patch(name string, pt types.PatchType, data []byte...
  function newFunctions (line 53) | func newFunctions(c *KubelessV1beta1Client, namespace string) *functions {

FILE: pkg/client/clientset/versioned/typed/kubeless/v1beta1/generated_expansion.go
  type FunctionExpansion (line 18) | type FunctionExpansion interface

FILE: pkg/client/clientset/versioned/typed/kubeless/v1beta1/kubeless_client.go
  type KubelessV1beta1Interface (line 25) | type KubelessV1beta1Interface interface
  type KubelessV1beta1Client (line 31) | type KubelessV1beta1Client struct
    method Functions (line 35) | func (c *KubelessV1beta1Client) Functions(namespace string) FunctionIn...
    method RESTClient (line 82) | func (c *KubelessV1beta1Client) RESTClient() rest.Interface {
  function NewForConfig (line 40) | func NewForConfig(c *rest.Config) (*KubelessV1beta1Client, error) {
  function NewForConfigOrDie (line 54) | func NewForConfigOrDie(c *rest.Config) *KubelessV1beta1Client {
  function New (line 63) | func New(c rest.Interface) *KubelessV1beta1Client {
  function setConfigDefaults (line 67) | func setConfigDefaults(config *rest.Config) error {

FILE: pkg/client/informers/externalversions/factory.go
  type sharedInformerFactory (line 35) | type sharedInformerFactory struct
    method Start (line 68) | func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
    method WaitForCacheSync (line 81) | func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{...
    method InformerFor (line 104) | func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFun...
    method Kubeless (line 129) | func (f *sharedInformerFactory) Kubeless() kubeless.Interface {
  function NewSharedInformerFactory (line 49) | func NewSharedInformerFactory(client versioned.Interface, defaultResync ...
  function NewFilteredSharedInformerFactory (line 56) | func NewFilteredSharedInformerFactory(client versioned.Interface, defaul...
  type SharedInformerFactory (line 121) | type SharedInformerFactory interface

FILE: pkg/client/informers/externalversions/generic.go
  type GenericInformer (line 31) | type GenericInformer interface
  type genericInformer (line 36) | type genericInformer struct
    method Informer (line 42) | func (f *genericInformer) Informer() cache.SharedIndexInformer {
    method Lister (line 47) | func (f *genericInformer) Lister() cache.GenericLister {
  method ForResource (line 53) | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersion...

FILE: pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go
  type NewInformerFunc (line 30) | type NewInformerFunc
  type SharedInformerFactory (line 33) | type SharedInformerFactory interface
  type TweakListOptionsFunc (line 38) | type TweakListOptionsFunc

FILE: pkg/client/informers/externalversions/kubeless/interface.go
  type Interface (line 27) | type Interface interface
  type group (line 32) | type group struct
    method V1beta1 (line 44) | func (g *group) V1beta1() v1beta1.Interface {
  function New (line 39) | func New(f internalinterfaces.SharedInformerFactory, namespace string, t...

FILE: pkg/client/informers/externalversions/kubeless/v1beta1/function.go
  type FunctionInformer (line 36) | type FunctionInformer interface
  type functionInformer (line 41) | type functionInformer struct
    method defaultInformer (line 79) | func (f *functionInformer) defaultInformer(client versioned.Interface,...
    method Informer (line 83) | func (f *functionInformer) Informer() cache.SharedIndexInformer {
    method Lister (line 87) | func (f *functionInformer) Lister() v1beta1.FunctionLister {
  function NewFunctionInformer (line 50) | func NewFunctionInformer(client versioned.Interface, namespace string, r...
  function NewFilteredFunctionInformer (line 57) | func NewFilteredFunctionInformer(client versioned.Interface, namespace s...

FILE: pkg/client/informers/externalversions/kubeless/v1beta1/interface.go
  type Interface (line 26) | type Interface interface
  type version (line 31) | type version struct
    method Functions (line 43) | func (v *version) Functions() FunctionInformer {
  function New (line 38) | func New(f internalinterfaces.SharedInformerFactory, namespace string, t...

FILE: pkg/client/listers/kubeless/v1beta1/expansion_generated.go
  type FunctionListerExpansion (line 23) | type FunctionListerExpansion interface
  type FunctionNamespaceListerExpansion (line 27) | type FunctionNamespaceListerExpansion interface

FILE: pkg/client/listers/kubeless/v1beta1/function.go
  type FunctionLister (line 29) | type FunctionLister interface
  type functionLister (line 38) | type functionLister struct
    method List (line 48) | func (s *functionLister) List(selector labels.Selector) (ret []*v1beta...
    method Functions (line 56) | func (s *functionLister) Functions(namespace string) FunctionNamespace...
  function NewFunctionLister (line 43) | func NewFunctionLister(indexer cache.Indexer) FunctionLister {
  type FunctionNamespaceLister (line 61) | type FunctionNamespaceLister interface
  type functionNamespaceLister (line 71) | type functionNamespaceLister struct
    method List (line 77) | func (s functionNamespaceLister) List(selector labels.Selector) (ret [...
    method Get (line 85) | func (s functionNamespaceLister) Get(name string) (*v1beta1.Function, ...

FILE: pkg/controller/function_controller.go
  constant maxRetries (line 49) | maxRetries        = 5
  constant funcKind (line 50) | funcKind          = "Function"
  constant funcAPIVersion (line 51) | funcAPIVersion    = "kubeless.io/v1beta1"
  constant functionFinalizer (line 52) | functionFinalizer = "kubeless.io/function"
  type FunctionController (line 56) | type FunctionController struct
    method Run (line 133) | func (c *FunctionController) Run(stopCh <-chan struct{}) {
    method HasSynced (line 152) | func (c *FunctionController) HasSynced() bool {
    method LastSyncResourceVersion (line 157) | func (c *FunctionController) LastSyncResourceVersion() string {
    method runWorker (line 161) | func (c *FunctionController) runWorker() {
    method processNextItem (line 167) | func (c *FunctionController) processNextItem() bool {
    method processItem (line 191) | func (c *FunctionController) processItem(key string) error {
    method startImageBuildJob (line 258) | func (c *FunctionController) startImageBuildJob(funcObj *kubelessApi.F...
    method ensureK8sResources (line 297) | func (c *FunctionController) ensureK8sResources(funcObj *kubelessApi.F...
    method deleteAutoscale (line 386) | func (c *FunctionController) deleteAutoscale(ns, name string) error {
    method deleteK8sResources (line 403) | func (c *FunctionController) deleteK8sResources(ns, name string) error {
  type Config (line 70) | type Config struct
  function NewFunctionController (line 76) | func NewFunctionController(cfg Config, smclient *monitoringv1alpha1.Moni...
  function functionObjChanged (line 440) | func functionObjChanged(oldFunctionObj, newFunctionObj *kubelessApi.Func...

FILE: pkg/controller/function_controller_test.go
  function findAction (line 20) | func findAction(fake *fake.Clientset, verb, resource string) ktesting.Ac...
  function hasAction (line 29) | func hasAction(fake *fake.Clientset, verb, resource string) bool {
  function TestDeleteK8sResources (line 33) | func TestDeleteK8sResources(t *testing.T) {
  function TestEnsureK8sResourcesWithDeploymentDefinitionFromConfigMap (line 114) | func TestEnsureK8sResourcesWithDeploymentDefinitionFromConfigMap(t *test...
  function TestEnsureK8sResourcesWithDeploymentDefinitionFromConfigMapUnknownKey (line 171) | func TestEnsureK8sResourcesWithDeploymentDefinitionFromConfigMapUnknownK...
  function TestEnsureK8sResourcesWithLivenessProbeFromConfigMap (line 192) | func TestEnsureK8sResourcesWithLivenessProbeFromConfigMap(t *testing.T) {
  function testFunc (line 246) | func testFunc() *kubelessApi.Function {
  function testRuntimeImages (line 294) | func testRuntimeImages() string {
  function testController (line 318) | func testController(clientset kubernetes.Interface, namespace string, co...

FILE: pkg/function-image-builder/image_builder.go
  function init (line 33) | func init() {
  function runCommand (line 42) | func runCommand(command string, args []string) error {
  function skopeoCopy (line 65) | func skopeoCopy(src, dst, srcCreds, dstCreds string, insecure bool) error {
  function newRootCmd (line 157) | func newRootCmd() *cobra.Command {
  function main (line 168) | func main() {

FILE: pkg/function-image-builder/layer-builder/description.go
  type Config (line 29) | type Config struct
  type HistoryEntry (line 51) | type HistoryEntry struct
  type Rootfs (line 59) | type Rootfs struct
  type Description (line 65) | type Description struct
    method New (line 78) | func (d *Description) New(descriptionFile io.Reader) error {
    method AddLayer (line 87) | func (d *Description) AddLayer(newLayer *Layer) {
    method Content (line 104) | func (d *Description) Content() ([]byte, error) {
    method ToLayer (line 109) | func (d *Description) ToLayer() (*Layer, error) {

FILE: pkg/function-image-builder/layer-builder/description_test.go
  function TestNewDescription (line 24) | func TestNewDescription(t *testing.T) {
  function TestAddLayerDescription (line 33) | func TestAddLayerDescription(t *testing.T) {
  function TestDescriptionToLayer (line 55) | func TestDescriptionToLayer(t *testing.T) {

FILE: pkg/function-image-builder/layer-builder/layer.go
  type Layer (line 27) | type Layer struct
    method New (line 33) | func (f *Layer) New(layerFile *os.File) error {

FILE: pkg/function-image-builder/layer-builder/layer_builder.go
  function copyReader (line 31) | func copyReader(src io.Reader, dst string) error {
  function copyFile (line 49) | func copyFile(src, dst string) error {
  function getLayer (line 59) | func getLayer(file string) (*Layer, error) {
  function saveNewDescription (line 73) | func saveNewDescription(content []byte, dir, contentChecksum string) err...
  function updateDescription (line 78) | func updateDescription(descriptionDir string, descriptionFile *os.File, ...
  function AddTarToLayer (line 92) | func AddTarToLayer(imageDir, tarFile string) error {

FILE: pkg/function-image-builder/layer-builder/layer_test.go
  function TestNewLayer (line 25) | func TestNewLayer(t *testing.T) {

FILE: pkg/function-image-builder/layer-builder/manifest.go
  type layer (line 26) | type layer struct
  type Manifest (line 33) | type Manifest struct
    method New (line 41) | func (m *Manifest) New(manifestFile io.Reader) error {
    method UpdateConfig (line 54) | func (m *Manifest) UpdateConfig(newConfig *Layer) {
    method AddLayer (line 60) | func (m *Manifest) AddLayer(newLayer *Layer) {

FILE: pkg/function-image-builder/layer-builder/manifest_test.go
  function TestNewManifest (line 24) | func TestNewManifest(t *testing.T) {
  function TestAddNewLayer (line 42) | func TestAddNewLayer(t *testing.T) {
  function TestUpdateConfig (line 61) | func TestUpdateConfig(t *testing.T) {

FILE: pkg/function-proxy/proxy.go
  function copyHeaders (line 32) | func copyHeaders(dst, src http.Header) {
  function handle (line 40) | func handle(ctx context.Context, w http.ResponseWriter, r *http.Request)...
  function handler (line 55) | func handler(w http.ResponseWriter, r *http.Request) {
  function health (line 59) | func health(w http.ResponseWriter, r *http.Request) {
  function startNativeDaemon (line 72) | func startNativeDaemon() {
  function main (line 83) | func main() {

FILE: pkg/function-proxy/utils/proxy-utils.go
  function PromHTTPHandler (line 55) | func PromHTTPHandler() http.Handler {
  function init (line 59) | func init() {
  type loggingResponseWriter (line 82) | type loggingResponseWriter struct
    method WriteHeader (line 91) | func (lrw *loggingResponseWriter) WriteHeader(code int) {
  function newLoggingResponseWriter (line 87) | func newLoggingResponseWriter(w http.ResponseWriter) *loggingResponseWri...
  function logReq (line 96) | func logReq(handler http.Handler) http.Handler {
  function copyHeaders (line 111) | func copyHeaders(dst, src http.Header) {
  type Handle (line 120) | type Handle
  function Handler (line 124) | func Handler(w http.ResponseWriter, r *http.Request, h Handle) {
  function NewServer (line 161) | func NewServer(mux *http.ServeMux) *http.Server {
  function GracefulShutdown (line 167) | func GracefulShutdown(server *http.Server) {

FILE: pkg/functions/params.go
  type Extension (line 25) | type Extension struct
  type Event (line 32) | type Event struct
  type Context (line 42) | type Context struct

FILE: pkg/langruntime/langruntime.go
  constant PhaseInstallation (line 19) | PhaseInstallation = "installation"
  constant PhaseCompilation (line 21) | PhaseCompilation = "compilation"
  constant PhaseRuntime (line 23) | PhaseRuntime = "runtime"
  type Langruntimes (line 27) | type Langruntimes struct
    method ReadConfigMap (line 80) | func (l *Langruntimes) ReadConfigMap() {
    method GetRuntimes (line 90) | func (l *Langruntimes) GetRuntimes() []string {
    method IsValidRuntime (line 101) | func (l *Langruntimes) IsValidRuntime(runtime string) bool {
    method getAvailableRuntimesPerTrigger (line 110) | func (l *Langruntimes) getAvailableRuntimesPerTrigger(imageType string...
    method getVersionFromRuntime (line 123) | func (l *Langruntimes) getVersionFromRuntime(runtime string) string {
    method GetRuntimeInfo (line 129) | func (l *Langruntimes) GetRuntimeInfo(runtime string) (RuntimeInfo, er...
    method GetLivenessProbeInfo (line 141) | func (l *Langruntimes) GetLivenessProbeInfo(runtime string, port int) ...
    method findRuntimeVersion (line 165) | func (l *Langruntimes) findRuntimeVersion(runtimeWithVersion string) (...
    method findImage (line 180) | func (l *Langruntimes) findImage(phase string, runtime RuntimeVersion)...
    method GetFunctionImage (line 190) | func (l *Langruntimes) GetFunctionImage(runtime string) (string, error) {
    method GetImageSecrets (line 214) | func (l *Langruntimes) GetImageSecrets(runtime string) ([]v1.LocalObje...
    method GetInitContainerSecrets (line 241) | func (l *Langruntimes) GetInitContainerSecrets(runtime, name string) (...
    method GetBuildContainer (line 283) | func (l *Langruntimes) GetBuildContainer(runtime, depsChecksum string,...
    method UpdateDeployment (line 336) | func (l *Langruntimes) UpdateDeployment(dpm *appsv1.Deployment, volPat...
    method GetCompilationContainer (line 359) | func (l *Langruntimes) GetCompilationContainer(runtime, funcName strin...
  type Image (line 33) | type Image struct
  type Secret (line 42) | type Secret struct
  type RuntimeVersion (line 47) | type RuntimeVersion struct
  type ImageSecret (line 55) | type ImageSecret struct
  type RuntimeInfo (line 61) | type RuntimeInfo struct
  function New (line 70) | func New(config *v1.ConfigMap) *Langruntimes {
  function appendToCommand (line 267) | func appendToCommand(orig string, command ...string) string {
  function parseEnv (line 274) | func parseEnv(env map[string]string) []v1.EnvVar {
  function name2phase (line 391) | func name2phase(name string) string {

FILE: pkg/langruntime/langruntime_test.go
  function TestMain (line 17) | func TestMain(m *testing.M) {
  function check (line 22) | func check(clientset *fake.Clientset, lr *Langruntimes, runtime, fname s...
  function TestGetFunctionFileNames (line 36) | func TestGetFunctionFileNames(t *testing.T) {
  function TestGetFunctionImage (line 44) | func TestGetFunctionImage(t *testing.T) {
  function TestGetLivenessProbe (line 73) | func TestGetLivenessProbe(t *testing.T) {
  function TestGetRuntimes (line 93) | func TestGetRuntimes(t *testing.T) {
  function TestGetBuildContainer (line 104) | func TestGetBuildContainer(t *testing.T) {
  function TestGetBuildContainerWithBundledDeps (line 140) | func TestGetBuildContainerWithBundledDeps(t *testing.T) {

FILE: pkg/langruntime/langruntimetestutils.go
  function AddFakeConfig (line 12) | func AddFakeConfig(clientset *fake.Clientset) {
  function SetupLangRuntime (line 66) | func SetupLangRuntime(clientset *fake.Clientset) *Langruntimes {

FILE: pkg/registry/registry.go
  type Credentials (line 32) | type Credentials struct
  type Registry (line 40) | type Registry struct
    method getTags (line 87) | func (r *Registry) getTags(body []byte) ([]string, error) {
    method tagURL (line 113) | func (r *Registry) tagURL(img string) (string, error) {
    method doRequest (line 183) | func (r *Registry) doRequest(url string) ([]byte, error) {
    method ImageExists (line 216) | func (r *Registry) ImageExists(id, tag string) (bool, error) {
  type tagv1 (line 46) | type tagv1 struct
  type tagListV2 (line 51) | type tagListV2 struct
  type dockerCfg (line 56) | type dockerCfg struct
  function New (line 61) | func New(config v1.Secret) (*Registry, error) {
  function findProperty (line 125) | func findProperty(src, property string) (string, error) {
  type authResponse (line 134) | type authResponse struct
  function doRequestWithAuth (line 139) | func doRequestWithAuth(authInfo, url string, client *http.Client) ([]byt...

FILE: pkg/registry/registry_test.go
  function TestNew (line 10) | func TestNew(t *testing.T) {
  function TestTagURLV1 (line 34) | func TestTagURLV1(t *testing.T) {
  function TestTagURLV2 (line 48) | func TestTagURLV2(t *testing.T) {
  function TestGetTagsV1 (line 62) | func TestGetTagsV1(t *testing.T) {
  function TestGetTagsV2 (line 78) | func TestGetTagsV2(t *testing.T) {

FILE: pkg/utils/configlocation.go
  type ConfigLocation (line 4) | type ConfigLocation struct

FILE: pkg/utils/exec.go
  constant stdinChannel (line 19) | stdinChannel  = 0
  constant stdoutChannel (line 20) | stdoutChannel = 1
  constant stderrChannel (line 21) | stderrChannel = 2
  constant errChannel (line 22) | errChannel    = 3
  type Cmd (line 26) | type Cmd struct
    method RoundTripCallback (line 35) | func (c *Cmd) RoundTripCallback(conn *websocket.Conn) (*http.Response,...
  type RoundTripCallback (line 114) | type RoundTripCallback
  type WebsocketRoundTripper (line 118) | type WebsocketRoundTripper struct
    method RoundTrip (line 124) | func (d *WebsocketRoundTripper) RoundTrip(r *http.Request) (*http.Resp...
  function ExecRoundTripper (line 149) | func ExecRoundTripper(conf *rest.Config, f RoundTripCallback) (http.Roun...
  function Exec (line 164) | func Exec(client corev1.CoreV1Interface, pod, namespace string, opts v1....

FILE: pkg/utils/exec_test.go
  function TestExecURL (line 11) | func TestExecURL(t *testing.T) {

FILE: pkg/utils/k8sutil.go
  constant defaultTimeout (line 53) | defaultTimeout = "180"
  function GetClient (line 57) | func GetClient() kubernetes.Interface {
  function BuildOutOfClusterConfig (line 72) | func BuildOutOfClusterConfig() (*rest.Config, error) {
  function GetClientOutOfCluster (line 96) | func GetClientOutOfCluster() kubernetes.Interface {
  function GetAPIExtensionsClientOutOfCluster (line 111) | func GetAPIExtensionsClientOutOfCluster() clientsetAPIExtensions.Interfa...
  function GetAPIExtensionsClientInCluster (line 124) | func GetAPIExtensionsClientInCluster() clientsetAPIExtensions.Interface {
  function GetFunctionClientInCluster (line 138) | func GetFunctionClientInCluster() (versioned.Interface, error) {
  function GetKubelessClientOutCluster (line 153) | func GetKubelessClientOutCluster() (versioned.Interface, error) {
  function GetDefaultNamespace (line 167) | func GetDefaultNamespace() string {
  function GetFunction (line 179) | func GetFunction(funcName, ns string) (kubelessApi.Function, error) {
  function CreateFunctionCustomResource (line 198) | func CreateFunctionCustomResource(kubelessClient versioned.Interface, f ...
  function UpdateFunctionCustomResource (line 207) | func UpdateFunctionCustomResource(kubelessClient versioned.Interface, f ...
  function PatchFunctionCustomResource (line 213) | func PatchFunctionCustomResource(kubelessClient versioned.Interface, f *...
  function DeleteFunctionCustomResource (line 223) | func DeleteFunctionCustomResource(kubelessClient versioned.Interface, fu...
  function GetFunctionCustomResource (line 233) | func GetFunctionCustomResource(kubelessClient versioned.Interface, funcN...
  function GetPodsByLabel (line 244) | func GetPodsByLabel(c kubernetes.Interface, ns, k, v string) (*v1.PodLis...
  function GetReadyPod (line 256) | func GetReadyPod(pods *v1.PodList) (v1.Pod, error) {
  function GetLocalHostname (line 273) | func GetLocalHostname(config *rest.Config, funcName string) (string, err...
  function doRESTReq (line 283) | func doRESTReq(restIface rest.Interface, groupVersion, verb, resource, e...
  function CreateAutoscale (line 320) | func CreateAutoscale(client kubernetes.Interface, hpa v2beta1.Horizontal...
  function UpdateAutoscale (line 326) | func UpdateAutoscale(client kubernetes.Interface, hpa v2beta1.Horizontal...
  function DeleteAutoscale (line 332) | func DeleteAutoscale(client kubernetes.Interface, name, ns string) error {
  function DeleteServiceMonitor (line 341) | func DeleteServiceMonitor(smclient monitoringv1alpha1.MonitoringV1alpha1...
  function initializeEmptyMapsInDeployment (line 352) | func initializeEmptyMapsInDeployment(deployment *appsv1.Deployment) {
  function MergeDeployments (line 374) | func MergeDeployments(destinationDeployment *appsv1.Deployment, sourceDe...
  function FunctionObjAddFinalizer (line 407) | func FunctionObjAddFinalizer(kubelessClient versioned.Interface, funcObj...
  function FunctionObjHasFinalizer (line 414) | func FunctionObjHasFinalizer(funcObj *kubelessApi.Function, finalizerStr...
  function FunctionObjRemoveFinalizer (line 425) | func FunctionObjRemoveFinalizer(kubelessClient versioned.Interface, func...
  function GetAnnotationsFromCRD (line 443) | func GetAnnotationsFromCRD(clientset clientsetAPIExtensions.Interface, n...
  function GetRandString (line 452) | func GetRandString(n int) (string, error) {
  function GetSecretsAsLocalObjectReference (line 461) | func GetSecretsAsLocalObjectReference(secrets ...string) []v1.LocalObjec...

FILE: pkg/utils/k8sutil_test.go
  function objBody (line 24) | func objBody(object interface{}) io.ReadCloser {
  function fakeConfig (line 32) | func fakeConfig() *rest.Config {
  function TestGetLocalHostname (line 45) | func TestGetLocalHostname(t *testing.T) {
  function TestCreateAutoscaleResource (line 58) | func TestCreateAutoscaleResource(t *testing.T) {
  function TestUpdateAutoscaleResource (line 81) | func TestUpdateAutoscaleResource(t *testing.T) {
  function TestDeleteAutoscaleResource (line 120) | func TestDeleteAutoscaleResource(t *testing.T) {
  function TestInitializeEmptyMapsInDeployment (line 143) | func TestInitializeEmptyMapsInDeployment(t *testing.T) {
  function TestMergeDeployments (line 167) | func TestMergeDeployments(t *testing.T) {
  function TestGetAnnotationsFromCRD (line 314) | func TestGetAnnotationsFromCRD(t *testing.T) {

FILE: pkg/utils/kubelessutil.go
  constant secretsMountPath (line 55) | secretsMountPath = "/var/run/secrets/kubeless.io"
  function GetFunctionPort (line 58) | func GetFunctionPort(clientset kubernetes.Interface, namespace, function...
  function IsJSON (line 67) | func IsJSON(s string) bool {
  function appendToCommand (line 73) | func appendToCommand(orig string, command ...string) string {
  function getProvisionContainer (line 80) | func getProvisionContainer(function, checksum, fileName, handler, conten...
  function addDefaultLabel (line 162) | func addDefaultLabel(labels map[string]string) map[string]string {
  function hasDefaultLabel (line 170) | func hasDefaultLabel(labels map[string]string) bool {
  function splitHandler (line 177) | func splitHandler(handler string) (string, string, error) {
  function getFileName (line 187) | func getFileName(handler, funcContentType, runtime string, lr *langrunti...
  function EnsureFuncConfigMap (line 204) | func EnsureFuncConfigMap(client kubernetes.Interface, funcObj *kubelessA...
  function serviceSpec (line 258) | func serviceSpec(funcObj *kubelessApi.Function) v1.ServiceSpec {
  function EnsureFuncService (line 278) | func EnsureFuncService(client kubernetes.Interface, funcObj *kubelessApi...
  function getRuntimeVolumeMount (line 312) | func getRuntimeVolumeMount(name string) v1.VolumeMount {
  function getChecksum (line 319) | func getChecksum(content string) (string, error) {
  function populatePodSpec (line 333) | func populatePodSpec(funcObj *kubelessApi.Function, lr *langruntime.Lang...
  function EnsureFuncImage (line 486) | func EnsureFuncImage(client kubernetes.Interface, funcObj *kubelessApi.F...
  function svcTargetPort (line 596) | func svcTargetPort(funcObj *kubelessApi.Function) int32 {
  function mergeMap (line 603) | func mergeMap(dst, src map[string]string) map[string]string {
  function EnsureFuncDeployment (line 614) | func EnsureFuncDeployment(client kubernetes.Interface, funcObj *kubeless...
  function CreateServiceMonitor (line 799) | func CreateServiceMonitor(smclient monitoringv1alpha1.MonitoringV1alpha1...
  function GetOwnerReference (line 837) | func GetOwnerReference(kind, apiVersion, name string, uid types.UID) ([]...
  function GetInClusterConfig (line 855) | func GetInClusterConfig() (*rest.Config, error) {
  function getConfigLocation (line 871) | func getConfigLocation(apiExtensionsClientset clientsetAPIExtensions.Int...
  function GetKubelessConfig (line 900) | func GetKubelessConfig(cli kubernetes.Interface, cliAPIExtensions client...
  function DryRunFmt (line 915) | func DryRunFmt(format string, trigger interface{}) (string, error) {
  function getCompressionType (line 935) | func getCompressionType(filename string) (compressionType string) {
  function GetContentType (line 951) | func GetContentType(filename string) (string, error) {
  function ParseContent (line 973) | func ParseContent(file, contentType string) (string, string, error) {
  function getFileSha256 (line 1019) | func getFileSha256(file string) (string, error) {
  function getSha256 (line 1035) | func getSha256(bytes []byte) (string, error) {

FILE: pkg/utils/kubelessutil_test.go
  function getEnvValueFromList (line 20) | func getEnvValueFromList(envName string, l []v1.EnvVar) string {
  function TestEnsureConfigMap (line 31) | func TestEnsureConfigMap(t *testing.T) {
  function TestEnsureFuncMapWithoutDeps (line 88) | func TestEnsureFuncMapWithoutDeps(t *testing.T) {
  function TestAvoidConfigMapOverwrite (line 160) | func TestAvoidConfigMapOverwrite(t *testing.T) {
  function TestEnsureFileNames (line 176) | func TestEnsureFileNames(t *testing.T) {
  function TestEnsureService (line 245) | func TestEnsureService(t *testing.T) {
  function TestUpdateFuncSvc (line 311) | func TestUpdateFuncSvc(t *testing.T) {
  function TestAvoidServiceOverwrite (line 368) | func TestAvoidServiceOverwrite(t *testing.T) {
  function TestEnsureImage (line 391) | func TestEnsureImage(t *testing.T) {
  function getDefaultFunc (line 473) | func getDefaultFunc(name, ns string) *kubelessApi.Function {
  function prepareDeploymentTest (line 520) | func prepareDeploymentTest(funcName string) (*fake.Clientset, []metav1.O...
  function TestEnsureDeployment (line 535) | func TestEnsureDeployment(t *testing.T) {
  function TestEnsureDeploymentWithoutFuncNorHandler (line 727) | func TestEnsureDeploymentWithoutFuncNorHandler(t *testing.T) {
  function TestEnsureDeploymentWithImage (line 744) | func TestEnsureDeploymentWithImage(t *testing.T) {
  function TestEnsureDeploymentWithoutFunc (line 763) | func TestEnsureDeploymentWithoutFunc(t *testing.T) {
  function TestEnsureUpdateDeployment (line 783) | func TestEnsureUpdateDeployment(t *testing.T) {
  function TestAvoidDeploymentOverwrite (line 813) | func TestAvoidDeploymentOverwrite(t *testing.T) {
  function TestDeploymentWithUnsupportedRuntime (line 829) | func TestDeploymentWithUnsupportedRuntime(t *testing.T) {
  function TestDeploymentWithTimeout (line 843) | func TestDeploymentWithTimeout(t *testing.T) {
  function TestDeploymentWithPrebuiltImage (line 862) | func TestDeploymentWithPrebuiltImage(t *testing.T) {
  function TestDeploymentWithVolumes (line 883) | func TestDeploymentWithVolumes(t *testing.T) {
  function TestEnsureDeploymentWithAffinityOverridden (line 916) | func TestEnsureDeploymentWithAffinityOverridden(t *testing.T) {
  function doesNotContain (line 940) | func doesNotContain(envs []v1.EnvVar, env v1.EnvVar) bool {
  function TestGetProvisionContainer (line 949) | func TestGetProvisionContainer(t *testing.T) {

FILE: pkg/utils/metrics.go
  type Metric (line 28) | type Metric struct
  type MetricsRetriever (line 40) | type MetricsRetriever interface
  type PrometheusMetricsHandler (line 45) | type PrometheusMetricsHandler struct
    method GetRawMetrics (line 104) | func (h *PrometheusMetricsHandler) GetRawMetrics(apiV1Client kubernete...
  function parseMetrics (line 47) | func parseMetrics(namespace, functionName string, rawMetrics []byte) ([]...
  function GetFunctionMetrics (line 116) | func GetFunctionMetrics(apiV1Client kubernetes.Interface, h MetricsRetri...
Condensed preview — 273 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,000K chars).
[
  {
    "path": ".circleci/config.yml",
    "chars": 7395,
    "preview": "version: 2\n\n## Definitions\nbuild_allways: &build_allways\n  filters:\n    tags:\n      only: /.*/\ndefaults: &defaults\n  env"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 165,
    "preview": "**Issue Ref**: [Issue number related to this PR or None]\n \n**Description**: \n\n[PR Description]\n\n**TODOs**:\n - [ ] Ready "
  },
  {
    "path": ".github/issue_template.md",
    "chars": 351,
    "preview": "**Is this a BUG REPORT or FEATURE REQUEST?**:\n\n**What happened**:\n\n**What you expected to happen**:\n\n**How to reproduce "
  },
  {
    "path": ".gitignore",
    "chars": 2548,
    "preview": "### Go ###\n# Binaries for programs and plugins\n*.exe\n*.dll\n*.so\n*.dylib\n\n# Test binary, build with `go test -c`\n*.test\n\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 3219,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 2699,
    "preview": "# Contributing Guidelines\n\n## License and CLA\n\nThe Kubeless license is Apache Software License V2\n\nWe do not currently a"
  },
  {
    "path": "LICENSE",
    "chars": 11346,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "Makefile",
    "chars": 2836,
    "preview": "GO = go\nGO_FLAGS =\nGOFMT = gofmt\nKUBECFG = kubecfg\nDOCKER = docker\nCONTROLLER_IMAGE = kubeless-function-controller:lates"
  },
  {
    "path": "OWNERS",
    "chars": 138,
    "preview": "Kubeless - A Bitnami Project\n\nEngineering manager:\n  - ppbaena\n\nEmeritus maintainers:\n  - ngtuna\n  - andresmgot\n  - angu"
  },
  {
    "path": "README.md",
    "chars": 3322,
    "preview": "# <img src=\"https://cloud.githubusercontent.com/assets/4056725/25480209/1d5bf83c-2b48-11e7-8db8-bcd650f31297.png\" alt=\"K"
  },
  {
    "path": "cmd/function-controller/function-controller.go",
    "chars": 2257,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/autoscale/autoscale.go",
    "chars": 3068,
    "preview": "/*\nCopyright 2016 Skippbox, Ltd.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fi"
  },
  {
    "path": "cmd/kubeless/autoscale/autoscaleCreate.go",
    "chars": 2535,
    "preview": "package autoscale\n\nimport (\n\t\"github.com/kubeless/kubeless/pkg/utils\"\n\t\"github.com/sirupsen/logrus\"\n\t\"github.com/spf13/c"
  },
  {
    "path": "cmd/kubeless/autoscale/autoscaleDelete.go",
    "chars": 1930,
    "preview": "/*\nCopyright 2016 Skippbox, Ltd.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fi"
  },
  {
    "path": "cmd/kubeless/autoscale/autoscaleList.go",
    "chars": 3415,
    "preview": "/*\nCopyright 2016 Skippbox, Ltd.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this fi"
  },
  {
    "path": "cmd/kubeless/autoscale/autoscaleList_test.go",
    "chars": 2821,
    "preview": "package autoscale\n\nimport (\n\t\"bytes\"\n\t\"strings\"\n\t\"testing\"\n\n\tav2alpha1 \"k8s.io/api/autoscaling/v2beta1\"\n\t\"k8s.io/api/cor"
  },
  {
    "path": "cmd/kubeless/autoscale/autoscale_test.go",
    "chars": 1596,
    "preview": "package autoscale\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"k8s.io/api/autoscaling/v2beta1\"\n\tmetav1 \"k8s.io/apimachinery/pkg/ap"
  },
  {
    "path": "cmd/kubeless/completion/completion.go",
    "chars": 2106,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/call.go",
    "chars": 3504,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/delete.go",
    "chars": 1481,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/deploy.go",
    "chars": 10312,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/describe.go",
    "chars": 3165,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/function.go",
    "chars": 8377,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/function_test.go",
    "chars": 17622,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/list.go",
    "chars": 6028,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/list_test.go",
    "chars": 6171,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/logs.go",
    "chars": 2173,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/top.go",
    "chars": 4118,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/top_test.go",
    "chars": 17839,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/function/update.go",
    "chars": 7670,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/getserverconfig/getServerConfig.go",
    "chars": 928,
    "preview": "package getserverconfig\n\nimport (\n\t\"strings\"\n\n\t\"github.com/kubeless/kubeless/pkg/langruntime\"\n\t\"github.com/kubeless/kube"
  },
  {
    "path": "cmd/kubeless/kubeless.go",
    "chars": 1533,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/topic/topic.go",
    "chars": 1220,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/topic/topicCreate.go",
    "chars": 2780,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/topic/topicDelete.go",
    "chars": 1800,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/topic/topicList.go",
    "chars": 1673,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/topic/topicPublish.go",
    "chars": 2885,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/cronjob/create.go",
    "chars": 4749,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/cronjob/cronjob_trigger.go",
    "chars": 2175,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/cronjob/delete.go",
    "chars": 1803,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/cronjob/list.go",
    "chars": 2240,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/cronjob/update.go",
    "chars": 4436,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/http/create.go",
    "chars": 5893,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/http/delete.go",
    "chars": 1779,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/http/http_trigger.go",
    "chars": 1120,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/http/list.go",
    "chars": 2173,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/http/update.go",
    "chars": 4901,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kafka/create.go",
    "chars": 3615,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kafka/delete.go",
    "chars": 1795,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kafka/kafka_trigger.go",
    "chars": 1132,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kafka/list.go",
    "chars": 2251,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kafka/update.go",
    "chars": 3380,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kinesis/create.go",
    "chars": 5137,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kinesis/delete.go",
    "chars": 1826,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kinesis/kinesis_trigger.go",
    "chars": 1246,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kinesis/list.go",
    "chars": 2302,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kinesis/publish.go",
    "chars": 4702,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kinesis/stream_create.go",
    "chars": 4166,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/kinesis/update.go",
    "chars": 4143,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/nats/create.go",
    "chars": 3580,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/nats/delete.go",
    "chars": 1781,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/nats/list.go",
    "chars": 2245,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/nats/nats_trigger.go",
    "chars": 1159,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/nats/publish.go",
    "chars": 1967,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/nats/update.go",
    "chars": 3353,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/trigger/trigger.go",
    "chars": 1491,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "cmd/kubeless/version/version.go",
    "chars": 939,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "docker/dev-environment/Dockerfile",
    "chars": 1118,
    "preview": "FROM docker:17.11.0-ce-dind\n\nENV GOPATH=/go\nENV PATH=$GOPATH/bin:/usr/local/go/bin:/usr/local/bats/bin:$PATH \\\n    CGO_E"
  },
  {
    "path": "docker/dev-environment/entry-point.sh",
    "chars": 551,
    "preview": "#!/bin/bash\n\nif [ ! -d \"$GOPATH/src/github.com/kubeless/kubeless\" ]; then\n    echo \"Kubeless directory not found\"\n    ex"
  },
  {
    "path": "docker/event-sources/kubernetes/Dockerfile",
    "chars": 452,
    "preview": "FROM bitnami/minideb:jessie\n\nRUN install_packages python3 curl ca-certificates git\nRUN curl https://bootstrap.pypa.io/ge"
  },
  {
    "path": "docker/event-sources/kubernetes/README.md",
    "chars": 508,
    "preview": "# Container to feed k8s events to kafka\n\n`events.py` is a Python 3.4 script, that uses `asyncio` and the Kubernetes pyth"
  },
  {
    "path": "docker/event-sources/kubernetes/events.py",
    "chars": 3189,
    "preview": "import asyncio\nimport logging\nimport json\n\nfrom kubernetes import client, config, watch\n\nfrom kafka import KafkaProducer"
  },
  {
    "path": "docker/function-controller/Dockerfile",
    "chars": 176,
    "preview": "FROM bitnami/minideb:jessie\n\nRUN install_packages ca-certificates\n\nADD kubeless-function-controller /kubeless-function-c"
  },
  {
    "path": "docker/function-image-builder/Dockerfile",
    "chars": 119,
    "preview": "FROM fedora:27\n\nRUN dnf install -y skopeo nodejs\n\nADD imbuilder /\nADD entrypoint.sh /\n\nENTRYPOINT [ \"/entrypoint.sh\" ]\n"
  },
  {
    "path": "docker/function-image-builder/entrypoint.sh",
    "chars": 961,
    "preview": "#!/bin/bash\n\n# Copyright (c) 2016-2017 Bitnami\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you"
  },
  {
    "path": "docker/runtime/README.md",
    "chars": 259,
    "preview": "Kubeless Runtimes has been migrated to it's own repository. You can find them here: https://github.com/kubeless/runtimes"
  },
  {
    "path": "docker/unzip/Dockerfile",
    "chars": 93,
    "preview": "FROM bitnami/minideb\nRUN install_packages unzip curl ca-certificates tar gzip bzip2 xz-utils\n"
  },
  {
    "path": "docs/GKE-deployment.md",
    "chars": 4651,
    "preview": "# Deploying Kubeless to Google Kubernetes Engine (GKE)\n\nThis guide goes over the required steps for deploying Kubeless i"
  },
  {
    "path": "docs/README.md",
    "chars": 259,
    "preview": "# Kubeless Docs\n\nThis folder holds the documentation that is served in [https://kubeless.io/docs](https://kubeless.io/do"
  },
  {
    "path": "docs/advanced-function-deployment.md",
    "chars": 7248,
    "preview": "# Deploying Kubeless Functions using Kubernetes API\n\nApart from using the `kubeless` CLI, it is possible to deploy Kubel"
  },
  {
    "path": "docs/architecture.md",
    "chars": 12724,
    "preview": "# Kubeless architecture\n\nThis doc covers the architectural design of Kubeless and directory structure of the repository."
  },
  {
    "path": "docs/autoscaling.md",
    "chars": 3209,
    "preview": "# Autoscaling function deployment in Kubeless\n\nThis document gives you an overview of how we do autoscaling for function"
  },
  {
    "path": "docs/building-functions.md",
    "chars": 5548,
    "preview": "# Build process for functions\n\n> **Warning**: This feature is still under heavy development\n\nKubeless includes a way of "
  },
  {
    "path": "docs/cronjob-triggers.md",
    "chars": 3784,
    "preview": "# Scheduling the trigger of a function \n\nKubeless has its own CronJobTrigger which uses [Kubernetes CronJob](https://kub"
  },
  {
    "path": "docs/debug-functions.md",
    "chars": 7608,
    "preview": "# Debug Kubeless Functions\n\nIn this document we will show how you can debug your function in order to spot possible erro"
  },
  {
    "path": "docs/debugging.md",
    "chars": 4757,
    "preview": "# Debugging Kubeless\n\nAs a developer you'll probably be interested on the investigation of Kubeless code. A possible res"
  },
  {
    "path": "docs/dev-guide.md",
    "chars": 8815,
    "preview": "# Kubeless developer guide\n\nThis will cover the steps need to be done in order to build your local development environme"
  },
  {
    "path": "docs/function-controller-configuration.md",
    "chars": 11518,
    "preview": "# Controller configurations for Functions\n\n## Using ConfigMap\n\nConfigurations for functions can be done in `ConfigMap`: "
  },
  {
    "path": "docs/http-triggers.md",
    "chars": 14774,
    "preview": "# Expose and secure Kubeless functions\n\nKubeless leverages [Kubernetes ingress](https://kubernetes.io/docs/concepts/serv"
  },
  {
    "path": "docs/implementing-new-runtime.md",
    "chars": 406,
    "preview": "# How to implement a new Kubeless run time\n\nRuntimes are developed in this repository:\n\n[https://github.com/kubeless/run"
  },
  {
    "path": "docs/implementing-new-trigger.md",
    "chars": 6344,
    "preview": "# How to add a new event source as Trigger\n\nKubeless [architecture](/docs/architecture) is built on core concepts of Fun"
  },
  {
    "path": "docs/kubeless-functions.md",
    "chars": 4631,
    "preview": "# Kubeless Functions\n\nFunctions are the main entity in Kubeless. It is possible to write Functions in different language"
  },
  {
    "path": "docs/kubeless-on-AKS.md",
    "chars": 1610,
    "preview": "# Kubeless on Azure Kubernetes Service\n\n## 1. Introduction\n\nThis guide goes over the required steps for deploying Kubele"
  },
  {
    "path": "docs/misc/kafka-pv-gke.yaml",
    "chars": 271,
    "preview": "apiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: kafka-pv\n  labels:\n    kubeless: kafka\nspec:\n  capacity:\n    sto"
  },
  {
    "path": "docs/misc/kubeless-grafana-dashboard.json",
    "chars": 7474,
    "preview": "{\n  \"id\": 1,\n  \"title\": \"Kubeless\",\n  \"description\": \"Dashboard for Kubeless\",\n  \"tags\": [],\n  \"style\": \"dark\",\n  \"timez"
  },
  {
    "path": "docs/misc/zookeeper-pv-gke.yaml",
    "chars": 283,
    "preview": "apiVersion: v1\nkind: PersistentVolume\nmetadata:\n  name: zookeeper-pv\n  labels:\n    kubeless: zookeeper\nspec:\n  capacity:"
  },
  {
    "path": "docs/monitoring.md",
    "chars": 604,
    "preview": "# Monitoring\n\n## Prometheus\n\nKubeless monitoring relies on Prometheus. The language runtimes are instrumented to automat"
  },
  {
    "path": "docs/proposals/decoupling-triggers-and-runtimes.md",
    "chars": 7649,
    "preview": "# Decoupling triggers and runtimes\n\n## Definition of the problem\nCurrently for each new runtime we need to add a contain"
  },
  {
    "path": "docs/proposals/http-triggers.md",
    "chars": 5534,
    "preview": "# http trigger improvements\n\nThough there is no standard on what http/https triggers of FAAS platform should support, mo"
  },
  {
    "path": "docs/pubsub-functions.md",
    "chars": 5785,
    "preview": "# PubSub events\n\nYou can trigger any Kubeless function by a PubSub mechanism. The PubSub function is expected to consume"
  },
  {
    "path": "docs/quick-start.md",
    "chars": 6501,
    "preview": "# Installation\n\nInstallation is made of three steps:\n\n* Download the `kubeless` CLI from the [release page](https://gith"
  },
  {
    "path": "docs/release-flow.md",
    "chars": 3855,
    "preview": "# Introduction\n\nKubeless leverages [travis-ci](https://travis-ci.org/) to construct an automated release flow. A release"
  },
  {
    "path": "docs/runtimes.md",
    "chars": 23113,
    "preview": "# Kubeless Runtime Variants\n\nBy default Kubeless has support for runtimes in different states: stable and incubator. You"
  },
  {
    "path": "docs/streaming-functions.md",
    "chars": 6850,
    "preview": "# Data Stream events\n\nKubeless lets you trigger any Kubeless function in response to ingested records into a data stream"
  },
  {
    "path": "docs/triggers.md",
    "chars": 1033,
    "preview": "# Triggers\n\nTo invoke deployed functions, you need to create **triggers**. A function can have multiple triggers, but ea"
  },
  {
    "path": "docs/troubleshooting.md",
    "chars": 1977,
    "preview": "# Troubleshooting\n\n## Installation\n\nIf installing using\n\n```console\nkubectl create -f kubeless.yaml --namespace kubeless"
  },
  {
    "path": "docs/use-existing-kafka.md",
    "chars": 6778,
    "preview": "# Use an existing Kafka cluster with Kubeless\n\nIn Kubeless [release page](https://github.com/kubeless/kubeless/releases)"
  },
  {
    "path": "examples/Makefile",
    "chars": 37407,
    "preview": "GIT_SHA1 ?= master\nBASE_URL := https://raw.githubusercontent.com/kubeless/kubeless/$(GIT_SHA1)\n\nget-python:\n\tkubeless fu"
  },
  {
    "path": "examples/README.md",
    "chars": 560,
    "preview": "# Examples\n\nThis directory contains basic examples for kubeless.\n\nSpecifically it contains examples that we can test qui"
  },
  {
    "path": "examples/ballerina/hello_with_conf/hello_with_conf.bal",
    "chars": 263,
    "preview": "import kubeless/kubeless;\nimport ballerina/io;\nimport ballerina/config;\n\npublic function bar(kubeless:Event event, kubel"
  },
  {
    "path": "examples/ballerina/hello_with_conf/kubeless.toml",
    "chars": 36,
    "preview": "[hello]\nuserid=\"john@ballerina.com\"\n"
  },
  {
    "path": "examples/ballerina/helloget.bal",
    "chars": 158,
    "preview": "import kubeless/kubeless;\n\npublic function foo(kubeless:Event event, kubeless:Context context) returns (string|error) {\n"
  },
  {
    "path": "examples/ballerina/hellowithdata.bal",
    "chars": 222,
    "preview": "import kubeless/kubeless;\nimport ballerina/io;\n\npublic function foo(kubeless:Event event, kubeless:Context context) retu"
  },
  {
    "path": "examples/dotnetcore/dependency-yaml.cs",
    "chars": 511,
    "preview": "using System;\r\nusing Kubeless.Functions;\r\nusing YamlDotNet.Serialization;\r\n\r\npublic class module\r\n{\r\n    public string h"
  },
  {
    "path": "examples/dotnetcore/dependency-yaml.csproj",
    "chars": 300,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n  </PropertyG"
  },
  {
    "path": "examples/dotnetcore/fibonacci.cs",
    "chars": 390,
    "preview": "using System;\r\nusing Kubeless.Functions;\r\n\r\npublic class module\r\n{\r\n    public int handler(Event k8Event, Context k8Cont"
  },
  {
    "path": "examples/dotnetcore/fibonacci.csproj",
    "chars": 238,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n  </PropertyG"
  },
  {
    "path": "examples/dotnetcore/helloget.cs",
    "chars": 167,
    "preview": "using System;\nusing Kubeless.Functions;\n\npublic class module\n{\n    public string handler(Event k8Event, Context k8Contex"
  },
  {
    "path": "examples/dotnetcore/helloget.csproj",
    "chars": 238,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n  </PropertyG"
  },
  {
    "path": "examples/dotnetcore/hellowithdata.cs",
    "chars": 166,
    "preview": "using System;\nusing Kubeless.Functions;\n\npublic class module\n{\n    public object handler(Event k8Event, Context k8Contex"
  },
  {
    "path": "examples/dotnetcore/hellowithdata.csproj",
    "chars": 238,
    "preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n  <PropertyGroup>\n    <TargetFramework>netstandard2.0</TargetFramework>\n  </PropertyG"
  },
  {
    "path": "examples/golang/go.mod",
    "chars": 73,
    "preview": "module function\n\ngo 1.14\n\nrequire (\n\tgithub.com/sirupsen/logrus v1.6.0\n)\n"
  },
  {
    "path": "examples/golang/helloget.go",
    "chars": 206,
    "preview": "package kubeless\n\nimport (\n\t\"github.com/kubeless/kubeless/pkg/functions\"\n)\n\n// Foo sample function\nfunc Foo(event functi"
  },
  {
    "path": "examples/golang/hellowithdata.go",
    "chars": 248,
    "preview": "package kubeless\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/kubeless/kubeless/pkg/functions\"\n)\n\n// Handler sample function with data"
  },
  {
    "path": "examples/golang/hellowithdeps.go",
    "chars": 283,
    "preview": "package kubeless\n\nimport (\n\t\"github.com/kubeless/kubeless/pkg/functions\"\n\t\"github.com/sirupsen/logrus\"\n)\n\n// Hello sampl"
  },
  {
    "path": "examples/java/HelloGet.java",
    "chars": 213,
    "preview": "package io.kubeless;\n\nimport io.kubeless.Event;\nimport io.kubeless.Context;\n\npublic class Foo {\n    public String foo(io"
  },
  {
    "path": "examples/java/HelloWithData.java",
    "chars": 249,
    "preview": "package io.kubeless;\n\nimport io.kubeless.Event;\nimport io.kubeless.Context;\n\npublic class Foo {\n    public String foo(io"
  },
  {
    "path": "examples/java/HelloWithDeps.java",
    "chars": 380,
    "preview": "package io.kubeless;\n\nimport io.kubeless.Event;\nimport io.kubeless.Context;\n\nimport org.joda.time.LocalTime;\n\npublic cla"
  },
  {
    "path": "examples/java/pom.xml",
    "chars": 825,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocat"
  },
  {
    "path": "examples/jvm/Readme.md",
    "chars": 138,
    "preview": "# JVM exampels\nThese are examples to run compiled jvm code in kubeless.\nThey should serve as a template to be able to us"
  },
  {
    "path": "examples/jvm/java/Readme.md",
    "chars": 252,
    "preview": "# Java on runtime JVM\n\n`gradle shadowJar` Build the jar with all deps\n\n`kubeless function deploy test --runtime jvm1.8 -"
  },
  {
    "path": "examples/jvm/java/build.gradle",
    "chars": 631,
    "preview": "buildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.github.jengelman.grad"
  },
  {
    "path": "examples/jvm/java/src/main/java/io/ino/Handler.java",
    "chars": 230,
    "preview": "package io.ino;\n\npublic class Handler {\n        public String sayHello(io.kubeless.Event event, io.kubeless.Context cont"
  },
  {
    "path": "examples/jvm/scala/Readme.md",
    "chars": 353,
    "preview": "# Scala on runtime JVM\n\n!! WIP the jar-file is to large for the storage backend, you have to pass a url to the jar file."
  },
  {
    "path": "examples/jvm/scala/build.sbt",
    "chars": 167,
    "preview": "\nassemblyJarName in assembly := \"scala-test.jar\"\norganization := \"de.inoio\"\nscalaVersion := \"2.12.1\"\nlibraryDependencies"
  },
  {
    "path": "examples/jvm/scala/project/assembly.sbt",
    "chars": 57,
    "preview": "addSbtPlugin(\"com.eed3si9n\" % \"sbt-assembly\" % \"0.14.7\")\n"
  },
  {
    "path": "examples/jvm/scala/project/build.properties",
    "chars": 20,
    "preview": "sbt.version=0.13.15\n"
  },
  {
    "path": "examples/jvm/scala/src/main/scala/de/inoio/Handler.scala",
    "chars": 160,
    "preview": "package de.inoio\n\nimport io.kubeless.{Context, Event}\n\nclass Handler {\n  def fooBar(event: Event, context: Context): Str"
  },
  {
    "path": "examples/nodejs/function.yaml",
    "chars": 255,
    "preview": "---\napiVersion: kubeless.io/v1beta1\nkind: Function\nmetadata:\n  name: hello\nspec:\n  handler: handler.hello\n  runtime: nod"
  },
  {
    "path": "examples/nodejs/function1.yaml",
    "chars": 256,
    "preview": "---\napiVersion: kubeless.io/v1beta1\nkind: Function\nmetadata:\n  name: hello\nspec:\n  handler: handler.foobar\n  runtime: no"
  },
  {
    "path": "examples/nodejs/helloget.js",
    "chars": 87,
    "preview": "module.exports = {\n  foo: function (event, context) {\n    return 'hello world!';\n  }\n}\n"
  },
  {
    "path": "examples/nodejs/hellostream.js",
    "chars": 735,
    "preview": "const from = require('from2');\nconst eos = require('end-of-stream');\n\nfunction fromString(string) {\n    return from(func"
  },
  {
    "path": "examples/nodejs/hellowithdata.js",
    "chars": 107,
    "preview": "module.exports = {\n  handler: (event, context) => {\n    console.log(event);\n    return event.data;\n  },\n};\n"
  },
  {
    "path": "examples/nodejs/hellowithdeps.js",
    "chars": 216,
    "preview": "'use strict';\n\nconst _ = require('lodash');\n\nmodule.exports = {\n    handler: (event, context) => {\n        _.assign(even"
  },
  {
    "path": "examples/nodejs/index.js",
    "chars": 132,
    "preview": "'use strict';\n\nmodule.exports = {\n    helloGet: require('./helloget').foo,\n    helloWithData: require('./hellowithdata')"
  },
  {
    "path": "examples/nodejs/package.json",
    "chars": 175,
    "preview": "{\n    \"name\": \"hellowithdeps\",\n    \"version\": \"0.0.1\",\n    \"dependencies\": {\n        \"end-of-stream\": \"^1.4.1\",\n        "
  },
  {
    "path": "examples/php/composer.json",
    "chars": 56,
    "preview": "{\n  \"require\": {\n      \"monolog/monolog\": \"^1.23\"\n  }\n}\n"
  },
  {
    "path": "examples/php/helloget.php",
    "chars": 67,
    "preview": "<?php\n\nfunction foo($event, $context) {\n  return \"hello world\";\n}\n\n"
  },
  {
    "path": "examples/php/hellowithdata.php",
    "chars": 79,
    "preview": "<?php\n\nfunction foo($event, $context) {\n  return json_encode($event->data);\n}\n\n"
  },
  {
    "path": "examples/php/hellowithdeps.php",
    "chars": 354,
    "preview": "<?php\n\nrequire 'vendor/autoload.php';\n\nuse Monolog\\Logger;\nuse Monolog\\Handler\\StreamHandler;\n\nfunction foo($event, $con"
  },
  {
    "path": "examples/python/Dockerfile",
    "chars": 340,
    "preview": "# Create a custom image with a python function\nFROM kubeless/python@sha256:565bebecb08d9a7b804c588105677a3572f10ff2032ce"
  },
  {
    "path": "examples/python/function.yaml",
    "chars": 208,
    "preview": "---\napiVersion: k8s.io/v1\nkind: Function\nmetadata:\n  name: function\nspec:\n  handler: hello.handler\n  runtime: python3.7\n"
  },
  {
    "path": "examples/python/function1.yaml",
    "chars": 577,
    "preview": "---\napiVersion: kubeless.io/v1beta1\nkind: Function\nmetadata:\n  name: function1\nspec:\n  handler: hello.foobar\n  runtime: "
  },
  {
    "path": "examples/python/helloget.py",
    "chars": 50,
    "preview": "def foo(event, context):\n    return \"hello world\"\n"
  },
  {
    "path": "examples/python/hellowithdata.py",
    "chars": 71,
    "preview": "def handler(event, context):\n    print(event)\n    return event['data']\n"
  },
  {
    "path": "examples/python/hellowithdeps.py",
    "chars": 35,
    "preview": "from hellowithdepshelper import foo"
  },
  {
    "path": "examples/python/hellowithdepshelper.py",
    "chars": 221,
    "preview": "from bs4 import BeautifulSoup\nimport urllib.request\n\ndef foo(event, context):\n    page = urllib.request.urlopen(\"https:/"
  },
  {
    "path": "examples/python/requirements.txt",
    "chars": 3,
    "preview": "bs4"
  },
  {
    "path": "examples/ruby/Gemfile",
    "chars": 45,
    "preview": "source 'https://rubygems.org'\n\ngem 'logging'\n"
  },
  {
    "path": "examples/ruby/function.yaml",
    "chars": 831,
    "preview": "---\napiVersion: kubeless.io/v1beta1\nkind: Function\nmetadata:\n  name: function\nspec:\n  handler: test.run\n  runtime: ruby2"
  },
  {
    "path": "examples/ruby/helloget.rb",
    "chars": 44,
    "preview": "def foo(event, context)\n  \"hello world\"\nend\n"
  },
  {
    "path": "examples/ruby/hellowithdata.rb",
    "chars": 75,
    "preview": "def handler(event, context)\n  puts event\n  JSON.generate(event[:data])\nend\n"
  },
  {
    "path": "examples/ruby/hellowithdeps.rb",
    "chars": 125,
    "preview": "require 'logging'\n\ndef foo(event, context)\n  logging = Logging.logger(STDOUT)\n  logging.info \"it works!\"\n  \"hello world\""
  },
  {
    "path": "examples/ruby/latest.rb",
    "chars": 592,
    "preview": "# Obtains the latest Kubeless release published \ndef handler(event, context)\n  require \"net/https\"\n  require \"uri\"\n  req"
  },
  {
    "path": "go.mod",
    "chars": 1976,
    "preview": "module github.com/kubeless/kubeless\n\ngo 1.12\n\nrequire (\n\tgithub.com/Azure/go-autorest v8.0.0+incompatible // indirect\n\tg"
  },
  {
    "path": "go.sum",
    "chars": 55011,
    "preview": "cloud.google.com/go v0.0.0-20160913182117-3b1ae45394a2/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.goog"
  },
  {
    "path": "hack/boilerplate.go.txt",
    "chars": 563,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "hack/update-codegen.sh",
    "chars": 1546,
    "preview": "#!/bin/bash\n\n# Copyright 2017 The Kubernetes Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\")"
  },
  {
    "path": "kubeless-non-rbac.jsonnet",
    "chars": 3997,
    "preview": "local k = import \"ksonnet.beta.1/k.libsonnet\";\nlocal runtimesSrc = import \"runtimes.jsonnet\";\n\nlocal objectMeta = k.core"
  },
  {
    "path": "kubeless-openshift.jsonnet",
    "chars": 721,
    "preview": "# Builds on kubeless.ksonnet to produce a deployable manifest on OpenShift 1.5\n# Modifies apiVersion for kubeless-contro"
  },
  {
    "path": "kubeless.jsonnet",
    "chars": 2701,
    "preview": "# Add RBAC role and binding on top of kubeless.jsonnet, to allow\n# kubeless controller to deploy/update/etc functions on"
  },
  {
    "path": "manifests/README.md",
    "chars": 257,
    "preview": "# Collection of manifests for development\n\n**NOTE: TO INSTALL KUBELESS USE A RELEASED MANIFEST AT https://github.com/kub"
  },
  {
    "path": "manifests/autoscaling/custom-metrics.yaml",
    "chars": 3124,
    "preview": "kind: Namespace\napiVersion: v1\nmetadata:\n  name: custom-metrics\n---\nkind: ServiceAccount\napiVersion: v1\nmetadata:\n  name"
  },
  {
    "path": "manifests/autoscaling/prometheus-operator.yaml",
    "chars": 1583,
    "preview": "apiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: prometheus-operator\nrules:\n- apiGroups"
  },
  {
    "path": "manifests/autoscaling/sample-metrics-app.yaml",
    "chars": 1498,
    "preview": "apiVersion: apps/v1beta1\nkind: Deployment\nmetadata:\n  labels:\n    app: sample-metrics-app\n  name: sample-metrics-app\nspe"
  },
  {
    "path": "manifests/autoscaling/sample-prometheus-instance.yaml",
    "chars": 1308,
    "preview": "apiVersion: rbac.authorization.k8s.io/v1beta1\nkind: ClusterRole\nmetadata:\n  name: prometheus\nrules:\n- apiGroups:\n  - \"\"\n"
  },
  {
    "path": "manifests/kinesis/kinesalite.yaml",
    "chars": 510,
    "preview": "---\napiVersion: v1\nkind: Service\nmetadata:\n  annotations:\n  name: kinesis\n  labels:\n    app: kinesis\nspec:\n  type: NodeP"
  },
  {
    "path": "manifests/monitoring/grafana-configmap.yaml",
    "chars": 53648,
    "preview": "apiVersion: v1\ndata:\n  grafana-net-2-dashboard.json: |\n    {\n      \"__inputs\": [{\n        \"name\": \"DS_PROMETHEUS\",\n     "
  },
  {
    "path": "manifests/monitoring/grafana-deployment.yaml",
    "chars": 1253,
    "preview": "apiVersion: extensions/v1beta1\nkind: Deployment\nmetadata:\n  name: grafana-core\n  namespace: monitoring\n  labels:\n    app"
  },
  {
    "path": "manifests/monitoring/grafana-job.yaml",
    "chars": 2095,
    "preview": "apiVersion: batch/v1\nkind: Job\nmetadata:\n  name: grafana-import-dashboards\n  namespace: monitoring\n  labels:\n    app: gr"
  },
  {
    "path": "manifests/monitoring/grafana-service.yaml",
    "chars": 224,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: grafana\n  namespace: monitoring\n  labels:\n    app: grafana\n    component:"
  },
  {
    "path": "manifests/monitoring/prometheus.yaml",
    "chars": 4962,
    "preview": "apiVersion: v1\nkind: Namespace\nmetadata:\n  name: monitoring\n---\nkind: ConfigMap\nmetadata:\n  name: prometheus-config\n  na"
  },
  {
    "path": "manifests/nats/nats-cluster.yaml",
    "chars": 111,
    "preview": "apiVersion: \"nats.io/v1alpha2\"\nkind: \"NatsCluster\"\nmetadata:\n  name: \"nats\"\nspec:\n  size: 2\n  version: \"1.1.0\"\n"
  },
  {
    "path": "manifests/ui/README.md",
    "chars": 170,
    "preview": "# Kubeless UI\n\nYou can find the latest manifest for deploying the UI in the releases page of the kubeless-ui repository:"
  },
  {
    "path": "pkg/apis/kubeless/register.go",
    "chars": 102,
    "preview": "package kubeless\n\nconst (\n\t// GroupName is ApiGroup for the Kubeless API\n\tGroupName = \"kubeless.io\"\n)\n"
  },
  {
    "path": "pkg/apis/kubeless/v1beta1/doc.go",
    "chars": 698,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/apis/kubeless/v1beta1/function.go",
    "chars": 2589,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/apis/kubeless/v1beta1/register.go",
    "chars": 1263,
    "preview": "package v1beta1\n\nimport (\n\tmetav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n\t\"k8s.io/apimachinery/pkg/runtime\"\n\t\"k8s.io/api"
  },
  {
    "path": "pkg/apis/kubeless/v1beta1/zz_generated.deepcopy.go",
    "chars": 3087,
    "preview": "// +build !ignore_autogenerated\n\n/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the"
  },
  {
    "path": "pkg/client/clientset/versioned/clientset.go",
    "chars": 3107,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/doc.go",
    "chars": 640,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/fake/clientset_generated.go",
    "chars": 2643,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/fake/doc.go",
    "chars": 640,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/fake/register.go",
    "chars": 1750,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/scheme/doc.go",
    "chars": 656,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/scheme/register.go",
    "chars": 1752,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/typed/kubeless/v1beta1/doc.go",
    "chars": 642,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/typed/kubeless/v1beta1/fake/doc.go",
    "chars": 633,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/typed/kubeless/v1beta1/fake/fake_function.go",
    "chars": 4456,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  },
  {
    "path": "pkg/client/clientset/versioned/typed/kubeless/v1beta1/fake/fake_kubeless_client.go",
    "chars": 1140,
    "preview": "/*\nCopyright (c) 2016-2017 Bitnami\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this"
  }
]

// ... and 73 more files (download for full content)

About this extraction

This page contains the full source code of the skippbox/kubeless GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 273 files (24.9 MB), approximately 263.6k tokens, and a symbol index with 485 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!