Code Monkey home page Code Monkey logo

helm-tiller's Introduction

Tillerless Helm v2 plugin

License CircleCI Release

Helm v2 plugin for using Tiller locally and in your CI/CD pipelines.

Blog post Tillerless Helm v2 on why Tillerless Helm is needed and what it solves.

Migration to Helm v3

Helm 3.0.0 has been released, check it out my blog post How to migrate from Helm v2 to Helm v3.

Installation

Install Helm client as per one of recommended ways.

Note: Initialize helm with helm init --client-only, flag --client-only is a must as otherwise you will get Tiller installed in to Kubernetes cluster.

Then install the latest plugin version:

helm plugin install https://github.com/rimusz/helm-tiller

Usage

Note: For a better security Tiller plugin comes with preset storage as Secret.

Usage:

helm tiller install
helm tiller start [tiller_namespace]
helm tiller start-ci [tiller_namespace]
helm tiller stop
helm tiller run [tiller_namespace] -- [command] [args]

Available Commands:
install   Manually install/upgrade Tiller binary
start     Start Tiller and open new pre-set shell
start-ci  Start Tiller without opening new shell
run       Start Tiller and run arbitrary command within the environment
stop      Stop Tiller

Available environment variables:

  • To silence plugin specific messages by setting HELM_TILLER_SILENT=true, only helm cli output will be printed.
  • To change default Tiller port by setting HELM_TILLER_PORT=44140, default is 44134.
  • To change default Tiller probe port by setting HELM_TILLER_PROBE_PORT=44141, default is 44135 - requires Helm >= 2.14.
  • To change Tiller storage to configmap by setting HELM_TILLER_STORAGE=configmap, default is secret.
  • To store Tiller logs in $HOME/.helm/plugins/helm-tiller/logs by setting HELM_TILLER_LOGS=true.
  • You can set a specific folder/file for Tiller logs by setting HELM_TILLER_LOGS_DIR=/some_folder/tiller.logs.
  • To change default Tiller maximum number of releases kept in release history by setting e.g. to 20 HELM_TILLER_HISTORY_MAX=20.
  • To not automatically create a namespace if it is missing by setting CREATE_NAMESPACE_IF_MISSING=false.

Tiller start examples

Start Tiller with pre-set bash shell HELM_HOST=127.0.0.1:44134, it is handy to use locally:

helm tiller start

The default working Tiller namespace is kube-system, you can set another one:

helm tiller start my_tiller_namespace

Tip: You can have many Tiller namespaces, e.g. one per team, just pass the name as an argument when you starting Tiller.

In CI pipelines you do not really need pre-set bash to be opened, so you can use:

helm tiller start-ci
export HELM_HOST=127.0.0.1:44134

Then your helm will know where to connect to Tiller and you do not need to make any changes in your CI pipelines.

And when you done stop the Tiller:

helm tiller stop

Tiller run examples

Another option for CI workflows.

Examples use of tiller run, that starts/stops tiller before/after the specified command:

helm tiller run helm list
helm tiller run my-tiller-namespace -- helm list
helm tiller run my-tiller-namespace -- bash -c 'echo running helm; helm list'

Handy bash aliases for use Tillerless locally:

alias hh="helm tiller run helm"
alias hr="helm tiller run"
alias ht="helm tiller start"
alias hts="helm tiller stop"

Examples of alias use:

# helm tiller run helm list
hh ls

# helm tiller run my-tiller-namespace -- helm list
hr my-tiller-namespace -- helm list

# helm tiller run my-tiller-namespace -- bash -c 'echo running helm; helm list'
hr my-tiller-namespace -- bash -c 'echo running helm; helm list'

Terraform Tiller examples

To use tiller with terraform-helm-provider, use helm tiller start-ci and set the helm provider's host to point to the locally started tiller.

$ helm tiller start-ci
provider "helm" {
  host = "127.0.0.1:44134"
  install_tiller = false
}

This will greatly simplify your usage of terraform-helm-provider as there is no longer a need to create service accounts, and deploy tiller along with the problems that come with it.

Using Tiller with Minikube

While using Minikube, it is important to stop, and restart tiller after a minikube delete and minikube start.

$ minikube delete
$ minikube start
$ helm tiller stop
$ helm tiller start

helm-tiller's People

Contributors

dakky avatar erks avatar excavador avatar foobaar avatar isen-ng avatar ivuk avatar jkroepke avatar jonerer avatar mumoshu avatar rimusz avatar twendt avatar typositoire avatar vbehar avatar vladislavpv avatar wf-ryanorth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

helm-tiller's Issues

Storage should be configurable

Thank you for a wonderful plugin, that really solves a very hard problem.

One small suggestion for an option:

Right now storage is set to secret which makes sense for some deployments, but not all. The developers we give access to our k8s cluster, cannot read/create secrets, so their deployments needs to be able to use configmaps.
We deploy secrets at the admin level, and they are using storage secrets, so it would be very cool to have this options configurable.

Helm Tiller Version Error with Helm installed via Homebrew

I installed Helm using Homebrew and installed Helm Tiller plugin. Tried to start Helm Tiller and encountered the following error.

Cortlands-MBP:Downloads cmoone$ helm plugin install https://github.com/rimusz/helm-tiller --version v0.8.4
Installed plugin: tiller
Cortlands-MBP:Downloads cmoone$ helm tiller start kube-system
Installed Helm version g7c22ef9
Installing Tiller vg7c22ef9 ...
version g7c22ef9 does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information.
Error: plugin "tiller" exited with error

--kube-context is not used

Great plugin!
It seems though that --kube-context to helm tiller does not have an effect. It uses the current-context, so it will deploy in current-context even though --kube-context is different, or if current-context is blank, will terminate with an error.

Plugin stopped working with helm

I have a docker helm tillerless docker image that uses alpine/helm:latest as base image, recently and new image was released and the plugin stopped working.

 $ docker run --entrypoint /bin/bash --name helm -ti --rm -v ~/.kube/config.yaml:/root/.kube/config prnjanuario/helm-tillerless:latest
bash-5.0# helm tiller start integration
Error: unknown shorthand flag: 'c' in -c
Installed Helm version
Installing Tiller v ...
Usage:
  semver bump (major|minor|patch|release|prerel <prerel>|build <build>) <version>
  semver compare <version> <other_version>
  semver --help
  semver --version

Arguments:
  <version>  A version must match the following regex pattern:
             "^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$".
             In english, the version must match X.Y.Z(-PRERELEASE)(+BUILD)
             where X, Y and Z are positive integers, PRERELEASE is an optionnal
             string composed of alphanumeric characters and hyphens and
             BUILD is also an optional string composed of alphanumeric
             characters and hyphens.

  <other_version>  See <version> definition.

  <prerel>  String that must be composed of alphanumeric characters and hyphens.

  <build>   String that must be composed of alphanumeric characters and hyphens.

Options:
  -v, --version          Print the version of this tool.
  -h, --help             Print this help message.

Commands:
  bump     Bump <version> by one of major, minor, patch, prerel, build
           or a forced potentialy conflicting version. The bumped version is
           shown to stdout.

  compare  Compare <version> with <other_version>, output to stdout the
           following values: -1 if <other_version> is newer, 0 if equal, 1 if
           older.
Error: plugin "tiller" exited with error
bash-5.0# helm version
version.BuildInfo{Version:"v3.0.0-alpha.1", GitCommit:"b9a54967f838723fe241172a6b94d18caf8bcdca", GitTreeState:"clean"}
bash-5.0# exit
exit

NOTE: The image prnjanuario/helm-tillerless:latest is now based on alpine/helm:2.14.0 so, to easily test this just pull the repository and change the base image to latest.

Feature Request: Automatically set HELM_TILLER_PORT to an unused port

It would be very nice if the plugin could automatically find and use an unused port for tiller. This would for example simplify simultaneous management of multiple clusters in different tabs. More importantly, however, it would fix the following bug: Currently (Version: v0.6.4), if I run helm tiller start and after that helm tiller start my-namespace, the second session would silently reuse tiller started in the first session.

Respect current shell

It'd be nice if this plugin respected the currently running shell instead of launching bash unconditionally. I use zsh personally, and that's what all my autocompletion, etc. are configured for. You could simply check if $SHELL is set, and if so use that, otherwise fall back to bash. This would also solve problems like #6 without needing to install bash into Alpine based images, for example.

migrating to helm3?

Can you provide some insights on how to migrate off helm2 w/ this plugin to helm3? I have live workloads I'd like to migrate but its not clear how I can even have both helm2 and helm3 client binaries w/ this plugin functioning.

helm version
version.BuildInfo{Version:"v3.1.1", GitCommit:"afe70585407b420d0097d07b21c47dc511525ac8", GitTreeState:"clean", GoVersion:"go1.13.8"}
helm2 version
Client: &version.Version{SemVer:"v2.16.3", GitCommit:"1ee0254c86d4ed6887327dabed7aa7da29d7eb0d", GitTreeState:"clean"}
helm2 --home ~/.helm2 init --client-only
helm2 --home ~/.helm2 plugin install https://github.com/rimusz/helm-tiller
$ helm2 --home ~/.helm2 tiller run -- helm2 list --all
Installed Helm version gafe7058
Installed Tiller version v2.16.3
Installing Tiller vgafe7058 ...
version gafe7058 does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information.
Error: plugin "tiller" exited with error

Tiller credentials persisted across "helm tiller start" sessions

Thanks for a great plugin!

Our usecase is like this:

(set credentials for AWS role)
$ helm tiller start
$....
$ (Ctrl-D)

(set credentials for other AWS role)
$ helm tiller start
$...
$ (Ctrl-D)

But this doesn't really work currently since the first tiller session will be re-used by the second "start" command, unless I run a "helm tiller stop" between them. I think it would better if the tiller session was tied to the shell session that "start" starts.

I saw this also mentioned in #33

Benefit of stoping helm tiller

Hey,

is there any benefit of stoping helm tiller in a ci cd environment ?

Would something bad happen if I do not do it?

Lost state?

Does helm-tiller maintain state somewhere? On a tiller stop/start, I lose my releases. I can see my release on my cluster but helm release does not return anything. I can also see releases from other namespaces but not in my own. Could it be because I didn't stop tiller using the stop command?

Here is an example of the steps to replicate this issue.

  • start tiller ๐Ÿ‘‰ helm tiller start
  • install release ๐Ÿ‘‰ helm install
  • list releases, release shows ๐Ÿ‘‰ helm list
  • computer restart
  • start tiller
  • list releases, no releases

What am I doing wrong?

`helm init` needed for `helm repo add`

Thank you so much for creating this plugin! The team I'm on started using this plugin last week, and it's working great.
Before we found this plugin, we looked into securing tiller by enabling TLS. Now after having explored both of those options (as ways to not have an unsecure/open endpoint in our K8s clusters), it seems like going tillerless is way easier than setting up a pipeline to maintain/update *.pem certs for TLS. (I wonder if this plugin can/should be mentioned on https://github.com/helm/helm/blob/master/docs/securing_installation.md...)

The only minor gotcha I ran into (when working through the steps described on https://rimusz.net/tillerless-helm/) is we sometimes do helm repo add, which (even when using this plugin) requires that helm init --client-only has been done. So perhaps it would be helpful to add mention of that to the blog post.

error: fork/exec: running in alpine docker...?

  1. start with this docker image
  2. add git cuz helm plugin install uses it
  3. make helm plugins folder
  4. install helm-tiller plugin
  5. try and run commands
  6. ๐Ÿ’ฃ
~/g/groovy-pipeline ๎‚ฐ ๎‚  tk/helm ๎‚ฐ docker run --rm -it --entrypoint=ash lachlanevenson/k8s-helm:v2.9.1
/ # apk add --update git
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.7/community/x86_64/APKINDEX.tar.gz
(1/5) Installing libssh2 (1.8.0-r2)
(2/5) Installing libcurl (7.61.0-r0)
(3/5) Installing expat (2.2.5-r0)
(4/5) Installing pcre2 (10.30-r0)
(5/5) Installing git (2.15.2-r0)
Executing busybox-1.27.2-r7.trigger
OK: 19 MiB in 17 packages
/ # mkdir -p $(helm home)/plugins
/ # helm plugin install https://github.com/rimusz/helm-tiller
Installed plugin: tiller
/ # helm tiller start
Error: fork/exec /root/.helm/plugins/helm-tiller/scripts/tiller.sh: no such file or directory
/ #

i'm baffled, any ideas?

helm_env

#36 breaks the setting of environment variables

See here:

b1d730f#diff-b2607c8a48fb3dc88826a1def0c39765L167

The removal of eval '$(helm_env "$@")' removes the actual setting of the environment variables.
In fact helm_env now simply echoes two lines of tiller host and namespace but does NOT set them
=> tiller tries to use the default namespace

Windows support?

Are there any plans to make the plugin work on windows? I'm currently getting:

 Error: fork/exec <HOME>\.helm\plugins\helm-tiller/scripts/tiller.sh: %1 is not a valid Win32 application.

tar: invalid number 'linux-amd64/tiller'

I tried to run the following command after installing the tiller plugin:

# helm tiller run tillerless -- helm list
Installed Helm version v2.14.1
Installing Tiller v2.14.1 ...
tar: invalid number 'linux-amd64/tiller'
Error: plugin "tiller" exited with error

I am using helm-tiller v0.8.3 and I ran that in a docker container for the record.

/tiller.sh: line 188: 69870 Terminated: 15

I do a helm tiller run -- helm delete --purge [release], it basically hangs for a while. The release is stuck in a DELETING state... I can't get rid of it because of this

What does this mean?

.helm/plugins/helm-tiller/scripts/tiller.sh: line 188: 69870 Terminated: 15          ./bin/tiller --storage=${HELM_TILLER_STORAGE} --listen=127.0.0.1:${HELM_TILLER_PORT} ${PROBE_LISTEN_FLAG} --history-max=${HELM_TILLER_HISTORY_MAX}  (wd: ~/.helm/plugins/helm-tiller)

$TMPDIR is not defined in all linux environments

Hey,

we just encountered problems with this plugin. The newest patch inferres, that $TMPDIR exists, which is not the case in all linux distributions, e.g. Arch.

I will provide an PR ASAP.

Best Regards,
Johann

Tiller isn't able to find pid file

My build pipeline doesn't work properly anymore after last update (~3h hours ago) of the tiller plugin.
The error message:


Stopping Tiller...
can not find tiller pid file /helm-tiller-44134.pid
Error: plugin "tiller" exited with error

Would you please rollback the pid changes?

[Question] Do I still need the tiller service account?

Sorry, I'm like super new to kubernetes in general but I'm kinda sick of always getting helm and tiller version mismatches.

So, do I still need the tiller service account If i'm using this tiller plugin instead of the remote tiller?

And.. I assume this plugin will get rid of helm and tiller version mismatches issues right?

Failed to create clusterrole when trying to deploy nginx-ingress

First of all, thanks for the great work. I'm currently using the helm integration you built for Google Cloud Build and came across this awesome work.

I was trying to use this plugin to install nginx-ingress in default namespace but it seems like tiller couldn't created a clusterole object that nginx-ingress needs.

Here is the error (Censored some confidential parts)

Error: release nginx-ingress failed: clusterroles.rbac.authorization.k8s.io "nginx-ingress" is forbidden: attempt to grant extra privileges: [PolicyRule{Resources:["configmaps"], APIGroups:[""], Verbs:["list"]} PolicyRule{Resources:["configmaps"], APIGroups:[""], Verbs:["watch"]} PolicyRule{Resources:["endpoints"], APIGroups:[""], Verbs:["list"]} PolicyRule{Resources:["endpoints"], APIGroups:[""], Verbs:["watch"]} PolicyRule{Resources:["nodes"], APIGroups:[""], Verbs:["list"]} PolicyRule{Resources:["nodes"], APIGroups:[""], Verbs:["watch"]} PolicyRule{Resources:["pods"], APIGroups:[""], Verbs:["list"]} PolicyRule{Resources:["pods"], APIGroups:[""], Verbs:["watch"]} PolicyRule{Resources:["secrets"], APIGroups:[""], Verbs:["list"]} PolicyRule{Resources:["secrets"], APIGroups:[""], Verbs:["watch"]} PolicyRule{Resources:["nodes"], APIGroups:[""], Verbs:["get"]} PolicyRule{Resources:["services"], APIGroups:[""], Verbs:["get"]} PolicyRule{Resources:["services"], APIGroups:[""], Verbs:["list"]} PolicyRule{Resources:["services"], APIGroups:[""], Verbs:["update"]} PolicyRule{Resources:["services"], APIGroups:[""], Verbs:["watch"]} PolicyRule{Resources:["ingresses"], APIGroups:["extensions"], Verbs:["get"]} PolicyRule{Resources:["ingresses"], APIGroups:["extensions"], Verbs:["list"]} PolicyRule{Resources:["ingresses"], APIGroups:["extensions"], Verbs:["watch"]} PolicyRule{Resources:["events"], APIGroups:[""], Verbs:["create"]} PolicyRule{Resources:["events"], APIGroups:[""], Verbs:["patch"]} PolicyRule{Resources:["ingresses/status"], APIGroups:["extensions"], Verbs:["update"]}] user=&{XXXXXXXXXX@XXXXXX [system:authenticated] map[user-assertion.cloud.google.com:[XXXXXXXXXXXXXXXXXXXXXXXXXXXXX]]} ownerrules=[PolicyRule{Resources:["selfsubjectaccessreviews" "selfsubjectrulesreviews"], APIGroups:["authorization.k8s.io"], Verbs:["create"]} PolicyRule{NonResourceURLs:["/api" "/api/" "/apis" "/apis/" "/healthz" "/swagger-2.0.0.pb-v1" "/swagger.json" "/swaggerapi" "/swaggerapi/*" "/version"], Verbs:["get"]}] ruleResolutionErrors=[]

Please advice what should I do

Bind Tiller on 127.0.0.1 instead of localhost

I run into the issue similar to helm/helm#4511, where localhost gets resolved to some other host due to internal DNS config.

Is it possible to start tiller with --listen=127.0.0.1:${HELM_TILLER_PORT} or --listen=:${HELM_TILLER_PORT} to make this more portable?

I can make a PR if this is acceptable.

allow concurrency

It is currently not possible to run concurrent helm tiller run -- helm ... commands. Any idea if that will be possible in the future? Right now I am using helmfile which can't deploy multiple charts simultaneously, nor delete them concurrently.

Sharing client host

Seems helm tiller start checks presence of already running tiller on the client host. If it finds it, the command sets HELM_HOST to let helm of the user to use the running tiller. However the running tiller uses ~/.kube/config and TILLER_* environment variables of the user, who started it. By doing this it gives users access even to different K8s clusters.

Expected behavior:

  • helm tiller start dynamically selects available port and always starts new tiller, HELM_HOST is set accordingly
  • tiller does not accept requests from "unknown" shells (maybe by comparing signatures of ~/.kube/config files)
  • tiller exits on exit from sub-shell

version 0.5.1 expects ./bin for tiller

On mac os x, helm installed with brew install kubernetes-helm.

Was using the tiller plugin since 0.3.1 and updated recently to 0.5.1 and started to see this error:

% helm tiller run -- helm ls
Installed Helm version v2.10.0
cp: cannot create regular file './bin/': Not a directory
Error: plugin "tiller" exited with error

Added extra tracing to the tiller.sh script and saw it trying to copy the tiller binary into a plugin subdirectory:

+ set -o errexit
++ pwd
+ CURRENT_FOLDER=/tmp/charts/test1
+ cd /Users/damian/.helm/plugins/helm-tiller
+ COMMAND=run
+ [[ ! -z run ]]
+ shift
+ case $COMMAND in
+ check_helm
+ command -v helm
+ check_install_tiller
++ helm version -c --short
++ awk '-F[:+]' '{print $2}'
++ cut -d ' ' -f 2
+ INSTALLED_HELM=v2.10.0
+ echo 'Installed Helm version v2.10.0'
Installed Helm version v2.10.0
+ '[' '!' -f ./bin/tiller ']'
+ command -v tiller
++ command -v tiller
+ EXISTING_TILLER=/usr/local/bin/tiller
+ cp /usr/local/bin/tiller ./bin/
cp: cannot create regular file './bin/': Not a directory
Error: plugin "tiller" exited with error

Once I created that ./bin directory inside the plugin directory, the tiller plugin worked as I expected.

mkdir $HOME/.helm/plugins/helm-tiller/bin

Latest commit is causing failure when running non-interactive: /dev/tty: No such device or address

The commit below is breaking all helm install when running non-interactive.

Error:
/home/***/.helm/plugins/helm-tiller/scripts/tiller.sh: line 79: /dev/tty: No such device or address

Commit:
tiller installation should not break the silence

Commit Snip:

16: REDIRECT=/dev/tty
17: if [[ "${HELM_TILLER_SILENT}" != "false" ]]; then
18:   REDIRECT=/dev/null
19: fi
. . .
79: echo "Installed Helm version $INSTALLED_HELM" &> $REDIRECT

System Info:

-bash-4.2$ lsb_release -a
LSB Version:    :core-4.1-amd64:core-4.1-noarch
Distributor ID: RedHatEnterpriseServer
Description:    Red Hat Enterprise Linux Server release 7.6 (Maipo)
Release:        7.6
Codename:       Maipo

-bash-4.2$ helm version
Client: &version.Version{SemVer:"v2.14.3", GitCommit:"0e7f3b6637f7af8fcfddb3d2941fcc7cbebb0085", GitTreeState:"clean"}

Helm Tiller Silent Not Working

Hey, we are happily using your helm tiller plugin but in the lastest version, we realized that even if the "HELM_TILLER_SILENT" variable is set to true by default, we get a tiller output which makes our CI fail because it expects input. I can reproduce it when I try to start it on my VM:
`
@management-vm:~$ helm tiller start-ci
Installed Helm version v2.14.3
Installed Tiller version v2.14.3
Helm and Tiller are the same version!
Set the following vars to use tiller:
export HELM_HOST=127.0.0.1:44134
Starting Tiller...
Tiller namespace: kube-system

@management-vm:~$ [main] 2019/09/27 13:04:35 Starting Tiller v2.14.3 (tls=false)
[main] 2019/09/27 13:04:35 GRPC listening on 127.0.0.1:44134
[main] 2019/09/27 13:04:35 Probes listening on 127.0.0.1:44135
[main] 2019/09/27 13:04:35 Storage driver is Secret
[main] 2019/09/27 13:04:35 Max history per release is 20

`
The last line expects input and therefore it fails.
Manually setting the helm tiller silent flag via export does not help either. Am I missing a new setting or is this an issue?

Thanks and best regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.