ksonnet / ksonnet-lib Goto Github PK
View Code? Open in Web Editor NEWCodegen for Kubernetes-API-compatible Jsonnet libraries
Home Page: https://ksonnet.io
License: Apache License 2.0
Codegen for Kubernetes-API-compatible Jsonnet libraries
Home Page: https://ksonnet.io
License: Apache License 2.0
e.g., there is some stuff like mixin:: {}
. We could probably use std.prune
to get rid of all of this, if we're ok with that solution.
When using deployment object, somehow the mixins get confused, so the top level ".withNamespace" sets it for the pod template, and not the deployment:
Repro:
local appDeployment = deployment
.new(
"heptio-server",
4,
serverContainer,
params.labels)
.withNamespace("heptio-svc");
Expected: deployment within given namespace.
Result: Sets the namespace in the pod spec.
Workaround:
The workaround is a bit hard to discover, but this works:
local appDeployment = deployment
.new(
"heptio-server",
params.replicas,
serverContainer,
myparams.labels)+
deployment.mixin.metadata.withNamespace("heptio-svc");
I'm seeing things like aPIVersion
which I expect is some "downcase first letter" rule that wasn't expecting an acronym.
I don't know if this actually matters though. Feel free to close.
Things in cluster
It appears that some keys from map labels which are using deployment.mixin.metadata.labels
get dropped for it's child replicaset.
Example:
local k = import "ksonnet.beta.2/k.libsonnet";
local container = k.extensions.v1beta1.deployment.mixin.spec.template.spec.containersType;
local containerPort = container.portsType;
local deployment = k.extensions.v1beta1.deployment;
local containerImage = "nginx";
local containerTag = "1.13.7-alpine";
local staticHttp =
local targetPort = 80;
container.new(containerImage, containerTag) +
container.ports(containerPort.newNamed("http", targetPort));
{
defaultConfig:: {
limits: {memory: "200Mi", cpu: "100m"},
labels: {tier: "web", example: "ok", aardvark: "ok"},
},
deployment(app, labels, limits)::
local comboLabels = std.mergePatch(self.defaultConfig.labels, {amazing: app});
deployment.new("nginx", 3, staticHttp, self.defaultConfig) +
deployment.mixin.metadata.labels(comboLabels) + {testing: comboLabels},
}.deployment('awesome', {}, {})
Output:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
aardvark: ok
amazing: awesome
example: ok
tier: web
name: nginx
spec:
replicas: 3
template:
metadata:
labels:
labels:
aardvark: ok
example: ok
tier: web
limits:
cpu: 100m
memory: 200Mi
spec:
containers:
- image: 1.13.7-alpine
name: nginx
ports:
- containerPort: 80
name: http
testing:
aardvark: ok
amazing: awesome
example: ok
tier: web
Notice: the amazing
key is dropped from the replicaset labels.
I'm still digging into why this is happening, but it appears to be with the library.
Both jsonnet and go-jsonnet are producing the same incorrect output.
There are a lot of expected strings that float around in k8s configurations.
Implement them as constants in this library (IfNotPresent, RollingUpdate, etc).
Optionally include validation.
http://ksonnet.heptio.com/docs/core-packages/ksonnet-lib.html#mixins -- tutorials link
OS Version: OS X High Sierra
Shell: Bash 3.2
K8s version: 1.8, minikube
Tying to follow: https://ksonnet-next-site.i.heptio.com/docs/tutorial#1-initialize-your-app-commands
bash-3.2$ kubectl get namespaces
NAME STATUS AGE
default Active 1h
ks-dev Active 9m
kube-public Active 1h
kube-system Active 1h
export GOPATH=/Users/ruben/go
INFO Using context 'ks-dev'
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x1b805ce]
goroutine 1 [running]:
github.com/ksonnet/ksonnet/cmd.resolveContext(0xc420553ca8, 0xc420399800, 0x7, 0x7ffeefbffb54, 0x6, 0x0, 0x0)
/Users/ruben/go/src/github.com/ksonnet/ksonnet/cmd/root.go:161 +0x3be
github.com/ksonnet/ksonnet/cmd.glob..func9(0x2528a00, 0xc42046eed0, 0x1, 0x3, 0x0, 0x0)
/Users/ruben/go/src/github.com/ksonnet/ksonnet/cmd/init.go:68 +0x237
github.com/ksonnet/ksonnet/vendor/github.com/spf13/cobra.(*Command).execute(0x2528a00, 0xc42046ed80, 0x3, 0x3, 0x2528a00, 0xc42046ed80)
/Users/ruben/go/src/github.com/ksonnet/ksonnet/vendor/github.com/spf13/cobra/command.go:656 +0x3f8
github.com/ksonnet/ksonnet/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0x252b260, 0x10067ac, 0xc42006c058, 0x0)
/Users/ruben/go/src/github.com/ksonnet/ksonnet/vendor/github.com/spf13/cobra/command.go:735 +0x339
github.com/ksonnet/ksonnet/vendor/github.com/spf13/cobra.(*Command).Execute(0x252b260, 0x0, 0x1e76419)
/Users/ruben/go/src/github.com/ksonnet/ksonnet/vendor/github.com/spf13/cobra/command.go:694 +0x2b
main.main()
/Users/ruben/go/src/github.com/ksonnet/ksonnet/main.go:33 +0x5b
It could be better.
Going further than #64 it's annoying to read the k8s.libsonnet
file. I'd like to have something like the following:
$ k8s doc -f ../lib/k8s.libsonnet core.v1.container
container(name string, image string)
// Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
withArgs(args []string)
withArgs(args string)
// Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
withCommand(command []string)
withCommand(command string)
...
Perhaps the doc comments could be shortened or excluded unless you drilled down on that specific method.
$ k8s doc -f ../lib/k8s.libsonnet core.v1.container.withArgs
// Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell
withArgs(args []string)
withArgs(args string)
So, I tried ksonnet-gen with k8s 1.6.0 and 1.7.0-beta.0 tags and they both didn't work. Here below is what I did:
// with k8s v1.6.0 tag
$ ksonnet-gen ~/workspace/gocode/kubernetes/src/k8s.io/kubernetes/api/openapi-spec/swagger.json .
Unrecognized Kubernetes version 'v1.6.0'
// with k8s v1.7.0-beta.0
$ ksonnet-gen ~/workspace/gocode/kubernetes/src/k8s.io/kubernetes/api/openapi-spec/swagger.json .
Failed to emit ref mixin:
Can't make API object from name with nil version in path: 'io.k8s.apimachinery.pkg.runtime.RawExtension'
cc/ @hausdorff
In beta.2
, something like this causes us to delete existing volumes:
daemonSet.mixin.spec.template.spec.volumes(someVolume)
While this appends them:
daemonSet.mixin.spec.template.spec.volumes([someVolume])
This is obviously wrong, and we should fix it.
The links between the main README and the tutorial doc are broken. I'm not 100% sure how to fix this, given that we don't want to break either the Github repo linking or the website linking. (Currently the Github linking works but the website doesn't).
Specifically: the tutorial link in http://ksonnet.heptio.com/docs/core-packages/ksonnet-lib.html#mixins and the readme link in http://ksonnet.heptio.com/docs/tutorial.html don't work.
This snippet is a stripped down version of the old tutorial, with examples removed. Would probably be good to develop some more complex examples (to demonstrate the value proposition better). (This could be an effort post-initial release.)
(template is provided in raw markdown here and in attached text file because GH doesn't support attaching markdown files :-( )
TUTORIAL_template.txt
The ksonnet readme
shows you how to create a default
deployment.json
file that lets you deploy an nginx container
to an existing Kubernetes cluster. This tutorial shows you how to:
This tutorial assumes that you have performed the following
tasks. For details, see the readme.
NOTE: All import paths are relative to the root of the
ksonnet* repository.
ksonnet lets you configure or modify any Kubernetes object.
For example, to customize the default <> deployment, you can write:
// TODO: provide ksonnet example
Save the file as customDeploy.libsonnet
and run:
jsonnet customDeploy.libsonnet
kubectl apply -f deployment.json
(here we seem to be looking at YAML we get from running
kubectl get deployment <appName> -o yaml
but in other examples
we're looking at JSON generated from ksonnet. Figure out, fix.)
And the generated YAML looks like this. You can see the new <>
and <> fields:
# TODO: provide example
ksonnet lets you define any Kubernetes object. For example,
you can define a container:
// TODO: update ksonnet example; container is probably a good one
// consider whether nginx is the right one for deployment
// (issue also in previous example)
Save this snippet as container.libsonnet
, and run:
jsonnet container.libsonnet
The JSON output looks like this:
TODO: fix up to be consistent with YAML vs JSON
across tutorial examples
(EXAMPLE)
You can include a liveness probe with your container:
// TODO: ksonnet example. Is liveness probe appropriate here?
Save the file again -- container.libsonnet
--
and run:
jsonnet container.libsonnet
(As above, YAML or JSON?)
The JSON output now looks like this:
(EXAMPLE)
Now you can define a pod that runs this container:
// TODO: ksonnet example
Save the file as pod.libsonnet
, and run the following commands
to deploy the pod to your cluster:
jsonnet pod.libsonnet // create pod.json
kubectl apply -f pod.json // apply pod definition to cluster
You've seen how to modify the default deployment by writing
mixins to add custom fields.
As the Jsonnet tutorial explains in more detail, mixins provide
dynamic inheritance, at runtime instead of compile time. This
approach means that different team members can define the
Kubernetes objects that they need. You can then mix them into
your master definition without having to copy all the details.
For example, you could write the following code to define a
container for your application:
// TODO: ksonnet example
And your teammate could write the following code to define
the VolumeMounts:
//TODO: ksonnet example
Then, you write a deployment definition for the container that
adds the VolumeMounts for logging using mixins:
//TODO: ksonnet example with mixins
Currently this is not included as part of the OpenAPI JSON spec for the Kubernetes API, so we'll have to generate it manually.
Instead of having to read the code I'd love to see a page of what constructors ksonnet provides.
Hi all,
opening separate issue per @hausdorff request here. My original observation here is repasted bellow for simplicity
--
as of now it looks that current head is busted (for beta.3)
actually @hausdorff example above won't work at all ...
for it to behave, unless I'm missing something, it seems one has to manually patch ksonnet.beta.3/k8s.libsonnet
along, at least, in those three places ...
diff --git a/ksonnet.beta.3/k8s.libsonnet b/ksonnet.beta.3/k8s.libsonnet
index 3b1bb7d..7cb3f16 100644
--- a/ksonnet.beta.3/k8s.libsonnet
+++ b/ksonnet.beta.3/k8s.libsonnet
@@ -348,7 +348,7 @@
// Deployment enables declarative updates for Pods and ReplicaSets.
deployment:: {
local kind = {kind: "Deployment"},
- new(name, replicas, containers, podLabels={app: name}):: apiVersion + kind + self.mixin.metadata.name(name) + self.mixin.spec.replicas(replicas) + self.mixin.spec.template.spec.containers(containers) + self.mixin.spec.template.metadata.labels(podLabels),
+ new(name, replicas, containers, podLabels={app: name}):: apiVersion + kind + self.mixin.metadata.withName(name) + self.mixin.spec.withReplicas(replicas) + self.mixin.spec.template.spec.withContainers(containers) + self.mixin.spec.template.metadata.withLabels(podLabels),
mixin:: {
// Standard object metadata.
metadata:: {
@@ -865,7 +865,7 @@
// The StatefulSet guarantees that a given network identity will always map to the same storage identity.
statefulSet:: {
local kind = {kind: "StatefulSet"},
- new(name, replicas, containers, volumeClaims, podLabels={app: name}):: apiVersion + kind + self.mixin.metadata.name(name) + self.mixin.spec.replicas(replicas) + self.mixin.spec.template.spec.containers(containers) + self.mixin.spec.volumeClaimTemplates(volumeClaims) + self.mixin.spec.template.metadata.labels(podLabels),
+ new(name, replicas, containers, volumeClaims, podLabels={app: name}):: apiVersion + kind + self.mixin.metadata.withName(name) + self.mixin.spec.withReplicas(replicas) + self.mixin.spec.template.spec.withContainers(containers) + self.mixin.spec.withVolumeClaimTemplates(volumeClaims) + self.mixin.spec.template.metadata.withLabels(podLabels),
mixin:: {
//
metadata:: {
@@ -4219,7 +4219,7 @@
// Namespace provides a scope for Names. Use of multiple namespaces is optional.
namespace:: {
local kind = {kind: "Namespace"},
- new(name):: apiVersion + kind + self.mixin.metadata.name(name),
+ new(name):: apiVersion + kind + self.mixin.metadata.withName(name),
mixin:: {
// Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
metadata:: {
--
this is straight from tip. top of ksonnet.beta.3/k8s.libsonnet
is
// AUTOGENERATED from the Kubernetes OpenAPI specification. DO NOT MODIFY.
// Kubernetes version: v1.7.0
// SHA of ksonnet-lib HEAD: 01423af3a22bb65ad77244563fa175d76458b012
// SHA of Kubernetes HEAD OpenAPI spec is generated from: d3ada0119e776222f11ec7945e6d860061339aad
@hausdorff fwiw this is on top of plain HEAD with just #81 applied (besides patch above). (host platform is macOS). Anything else I can do to help debug this ?
and thanks in advance!
I think we should enlarge the scope of the project and somehow support k8s 1.8 and 1.6
related to #70
Hook up automated CI for ksonnet-lib with TravisCI
I am looking for a good example to start writing my manifests using beta.2 at master branch. example/readme/hello-nginx.jsonnet
is still beta.1 and some demo* files at sigapp
branch don't work for master branch.
Good stuff!
The README.MD references a " ksonnet definition for the CockroachDB Helm chart".
The link 404s and the example appears not present in the repo.
apiVersion
usually takes the form group/version
. In the future, group
will be a domain, rather than a single word (as old groups are).
We currently don't handle this correctly. We need to get the real group out of the fields that look like this:
"x-kubernetes-group-version-kind": [
{
"Group": "rbac.authorization.k8s.io",
"Version": "v1alpha1",
"Kind": "ClusterRole"
}
]
I am trying a simple nginx service and getting the below error:
$ cat nginx-svc.jsonnet
local k = import "../../ksonnet.beta.1/k.libsonnet";
local srv = k.core.v1.service;
srv.default("nginx") +
srv.mixin.spec.ports("80")
$ jsonnet nginx-svc.jsonnet
RUNTIME ERROR: Field does not exist: ports
object <mixin>
../../ksonnet.beta.1/core.v1.libsonnet:3379:31-44 object <anonymous>
During manifestation
Is there a way to autogenerate ksonnet-gen/kubeversion/data.go ?
I would love to have it to try to support #70
I've been trying to use ksonnet-lib with Kubernetes 1.6.2 but there's no way I can get Kubernetes to accept the JSON code generated from the example file hello-nginx.jsonnet:
$ jsonnet --version
Jsonnet commandline interpreter v0.9.3
$ git clone https://github.com/ksonnet/ksonnet-lib
$ cd ksonnet-lib/examples/
$ jsonnet hello-nginx.jsonnet > hello-nginx.json
$ kubectl create -f hello-nginx.json
error: error validating "hello-nginx.json": error validating data: found invalid field hostMappings for v1.PodSpec; if you choose to ignore these errors, turn validation off with --validate=false
local params = std.extVar("__ksonnet/params").components["teamcity-server-instance"];
local k = import "k.libsonnet";
local deployment = k.apps.v1beta1.deployment;
local container = k.apps.v1beta1.deployment.mixin.spec.template.spec.containersType;
local containerPort = container.portsType;
local service = k.core.v1.service;
local servicePort = k.core.v1.service.mixin.spec.portsType;
local targetPort = params.containerPort;
local nodePort = params.nodePort;
local labels = {app: params.name};
VS Code Jsonnet Preview:
RUNTIME ERROR: Undefined external variable: __ksonnet/params
/Users/liaogang/Desktop/Anonym/CI/teamcity/components/teamcity-server-instance.jsonnet:1:16-45 thunk
/Users/liaogang/Desktop/Anonym/CI/teamcity/components/teamcity-server-instance.jsonnet:15:5-10 thunk
/Users/liaogang/ksonnet-lib/ksonnet.beta.3/k8s.libsonnet:8747:87-90 thunk
/Users/liaogang/ksonnet-lib/ksonnet.beta.3/k8s.libsonnet:8820:60-63 object
/Users/liaogang/ksonnet-lib/ksonnet.beta.3/k8s.libsonnet:8751:47-67 object
/Users/liaogang/Desktop/Anonym/CI/teamcity/components/teamcity-server-instance.jsonnet:31:21-30 thunk
/Users/liaogang/ksonnet-lib/ksonnet.beta.3/k.libsonnet:60:59-73 object
During manifestation
Sometimes you'll see stuff like containerPort.mixin
which is empty. It would be better to simply not emit it.
This will simplify usage of ksonnet embedding
jsonnet -J /path/to/ksonnet-lib <filename.libsonnet>
Into kubectl
.
The user will simply do:
kubectl <command> -<options> <filename.jsonet/libsonnet or ksonnet>
Using the beta2 generated api I was expecting something like this to work:
local esProxyStrategy =
strategy.new() +
strategy.rollingUpdate.maxSurge(2);
But it did not and @hausdorff told me that it was because the ksonnet-lib was not handling Kubernetes' intorstring type correctly.
We have a few open issues that are not urgent, but important to discuss, in #90. We merged to make the release window.
We need to come back, discuss, and fix them.
People would like to add some labels (probably it's required) to deployment and/or service. Need to have a clear way to do that with ksonnet. Here below I have this error:
$ cat nginx-deployment.jsonnet
local k = import "../../ksonnet.beta.1/k.libsonnet";
local container = k.core.v1.container;
local deployment = k.apps.v1beta1.deployment;
local prune = k.util.prune;
local label = {app: "nginx"};
// Create nginx container with container port 80 open.
local nginxContainer =
container.default("nginx", "nginx:1.13.0") +
container.helpers.namedPort("http", 80);
// Create default `Deployment` object from nginx container.
prune(deployment.default(
"nginx-deployment", nginxContainer) +
deployment.mixin.spec.replicas(5) +
deployment.mixin.spec.labels(label)
)
$ jsonnet nginx-deployment.jsonnet
RUNTIME ERROR: Field does not exist: labels
nginx-svc.jsonnet:16:3-30 thunk <thing>
../../ksonnet.beta.1/util.libsonnet:4:17-21
../../ksonnet.beta.1/util.libsonnet:4:8-22 thunk <a>
../../ksonnet.beta.1/util.libsonnet:4:8-33 function <anonymous>
../../ksonnet.beta.1/util.libsonnet:4:8-33 function <prune>
nginx-svc.jsonnet:(13:1)-(17:3)
Stuff like containerPort.new()
is a no-op. Consider just omitting this.
Currently kubecfg apply [--dry-run]
and kubecfg delete
aren't telling you what k8s resources are being created/updated/deleted.
We should make the -v flag default to solve this, and silence it explicitly with a flag.
The autogenerated k8s.libsonnet file throws the following STATIC ERROR:
k8s.libsonnet:4191:18-19: Expected token IDENTIFIER but got "::"
I'd like to use ksonnet on deployment, while I don't want to install neither jsonnet nor ksonnet. Instead I want to use the official Docker image containing ksonnet (and jsonnet) as a command. Of course it's easy to create such an image by myself. But the official image is preferable to my own ones, I think.
There are several references in k8s.libsonnet to the field hidden.core.v1.persistentVolumeClaim
which does not exist. However there is a field in core.v1.persistentVolumeClaim
which seems to fit the bill. I assume it was moved but the references weren't updated for some reason.
Hi,
Would be great to support OpenShift in ksonnet-gen.
openshift.json
go run main.go openshift.json out
Failed to parse definition name 'com.github.openshift.origin.pkg.authorization.apis.authorization.v1.RoleBindingRestrictionSpec'
exit status 1
Rather than have multiple parameters in the constructors, prefer to have a single (or no param) constructor.
Currently the constructors take a variable number of parameters, and it's hard to know what's required. For example:
Deployment - new(name, replicas, containers, podLabels={app: name})
Service - new(name, selector, ports)
Some of these params are text, some are other objects. It's unclear from the definition. To make it more confusing, there's also builder methods like "withContainers", which presumably provide same functionality.
Suggestion:
Have a consistent constructor (single name param for named objects, else no param constructor):
local mydep = deployment.new("frontend")
.withReplicas(2)
.withContainers(...);
As of today affinity and anti-affinity specification are very explicit, and lengthy to specify.
Node Affinity Examples:
https://github.com/kubernetes/kubernetes/blob/master/plugin/pkg/scheduler/algorithm/priorities/node_affinity_test.go
Inter-Pod Affinity Examples:
https://github.com/kubernetes/kubernetes/blob/master/plugin/pkg/scheduler/algorithm/priorities/interpod_affinity_test.go
imo ~90% users can typically understand affinity in terms of "groupby" and "spreadby".
groupby (type(pod,node), key=value)
There is more to this, but hopefully the gist is there.
Cursory examination seems to indicate that rbac.v1alpha1.roleRef
has a kind
field that is meant to refer to a different API group's kind
, rather than its own. This would make it an exception to the kind
blacklist rule.
While using jsonnet Jsonnet commandline interpreter v0.9.3 built-in locally on my Ubuntu 16.04 LTS machine, I noticed that jsonnet plus ksonnet yield invalid JSON:
$ git clone https://github.com/ksonnet/ksonnet-lib
$ cd ksonnet-lib/examples/readme/
$ jsonnet hello-nginx.jsonnet > json
$ kubectl create -f json
error: error validating "json": error validating data: [found invalid field hostMappings for v1.PodSpec, expected type array, for field spec.template.spec.containers, got map]; if you choose to ignore these errors, turn validation off with --validate=false
Hi,
I'm using ksonnet-gen
in https://github.com/amir/iron_jsonnet to generate k8s.libsonnet
. The library gets generated successfully but Kubernetes resource io.k8s.kubernetes.pkg.api.v1.LocalVolumeSource
gets translated to local::
which confuses Jsonnet. Looking at the k8s.libsonnet
in ksonnet.beta.2
I don't see that resource but I can't find how it's been renamed/removed. Is there a manual step involved after generating the library?
I'm using sed in my project to replace it but before contributing a fix I wanted to make sure it's something you've encountered before too.
Let's say I have this deployment:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: my-sample-deployment
This translates nicely when I make it one object like so:
deployment.new() +
deployment.mixin.metadata.name("my-sample-deployment")
But if I define my metadata first:
local metadata = deployment.mixin.metadataType;
local sampleDeploymentMetadata = metadata.new() +
metadata.name("my-sample-deployment");
I now only seem to have an awkward object to attach to the deployment like so:
deployment.new() +
{
"metadata": sampleDeploymentMetadata,
}
What do you think about supporting this kind of API:
deployment.new() +
deployment.mixin.metadata(sampleDeploymentMetadata);
Alternatively tell me what I've missed :)
note: you may be wondering about this code
deployment.new() +
sampleDeploymentMetadata
Well, this code yields:
apiVersion: extensions/v1beta1
kind: Deployment
name: my-sample-deployment
Pretty please.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.