Not another markup language. Framework for replacing Kubernetes YAML with Go.

Overview

Go Reference

Not another markup language.

Replace Kubernetes YAML with raw Go!

Say so long πŸ‘‹ to YAML and start using the Go πŸŽ‰ programming language to represent and deploy applications.

Take advantage of all the lovely features of Go.

Test your code directly in local Kubernetes using kind.

Get your application directly into Go instead of YAML and use it in controllers, operators, CRs/CRDs easily. Use the Go compiler to your advantage.

Quickstart

Check out the examples GitHub organization.

  • simple basic CLI example.
  • full CLI example with custom commands and flags.

Implement Deployable

As long as there is a Go system that implements this interface it can be used with naml. See examples for how to include an implementation in your project.

// Deployable is used to deploy applications.
type Deployable interface {

	// Install will attempt to install in Kubernetes
	Install(client *kubernetes.Clientset) error

	// Uninstall will attempt to uninstall in Kubernetes
	Uninstall(client *kubernetes.Clientset) error

	// Meta returns the Kubernetes native ObjectMeta which is used to manage applications with naml.
	Meta() *v1.ObjectMeta
}

About

This is a framework for infrastructure teams who need more than just conditional manifests.

This allows teams to start encapsulating, managing, and testing their applications in raw Go.

Teams can now buid controllers, operators, and custom toolchains using reliable, testable, and scalable Go.

The philosophy

The bet here is that any person confident in managing YAML for Kubernetes can also be equally as confident managing Go for Kubernetes.

The feature add is that no matter how good our YAML management tools get, they will never be as good as just plain Go when it comes to things like syntax checking, testing, shipping, and flexibility.

Nothing fancy

Feel free to fork this repository and begin using it for your team. There isn't anything special here. πŸ€·β€β™€ We use the same client the rest of Kubernetes does.

❎ No new tools.

❎ No charts.

❎ No templating at runtime.

❎ No vague error messages.

❎ No more YAML guessing/checking.

βœ… Just Go. πŸŽ‰

Features

✨ There is not a single .yaml file in this entire repository. ✨

  • Express applications in πŸŽ‰ Go instead of YAML.
  • Use the Go compiler to check your syntax.
  • Write real tests πŸ€“ using Go to check and validate your deployments.
  • Test your applications in Kubernetes using kind.
  • Define custom installation logic. What happens if it fails?
  • Define custom application registries. Multiple apps of the same flavor? No problem.
  • Use the latest client (the same client the rest of Kubernetes uses).

Getting Started

Check out the examples GitHub organization.

  • simple basic CLI example.
  • full CLI example with custom commands and flags.
Issues
  • Valast fails at runtime with type pointers

    Valast fails at runtime with type pointers

    Write now the type pointer generation is failing (at runtime!)

    panic: interface conversion: interface {} is *int, not *int32
    
    goroutine 1 [running]:
    github.com/naml-examples/simple.(*App).Install(0xc000391200, 0xc000508000, 0x0, 0xa)
            /home/nova/src/tests/app.go:86 +0xed9
    github.com/kris-nova/naml.Install(0x1afcaf0, 0xc000391200, 0xc0004a3bd0, 0x0)
            /home/nova/go/pkg/mod/github.com/kris-nova/[email protected]/cmd.go:386 +0xc7
    github.com/kris-nova/naml.RunCommandLineWithOptions.func2(0xc0004d2000, 0x1, 0x1)
            /home/nova/go/pkg/mod/github.com/kris-nova/[email protected]/cmd.go:160 +0x39f
    github.com/urfave/cli/v2.(*Command).Run(0xc000391440, 0xc0003fdf40, 0x0, 0x0)
            /home/nova/go/pkg/mod/github.com/urfave/cli/[email protected]/command.go:163 +0x4dd
    github.com/urfave/cli/v2.(*App).RunContext(0xc00025bd40, 0x1afc930, 0xc00019a010, 0xc0001a4000, 0x2, 0x2, 0x0, 0x0)
            /home/nova/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:313 +0x810
    github.com/urfave/cli/v2.(*App).Run(...)
            /home/nova/go/pkg/mod/github.com/urfave/cli/[email protected]/app.go:224
    github.com/kris-nova/naml.RunCommandLineWithOptions(0x1afcaf0, 0xc000391200)
            /home/nova/go/pkg/mod/github.com/kris-nova/[email protected]/cmd.go:316 +0xf2b
    github.com/kris-nova/naml.RunCommandLine(...)
            /home/nova/go/pkg/mod/github.com/kris-nova/[email protected]/cmd.go:51
    main.main()
            /home/nova/src/tests/cmd/main.go:42 +0xa5
    

    Looks like this is the culprit

    			Replicas: valast.Addr(1).(*int32),
    

    We should fix Valast to do something like this

    			Replicas: valast.Addr(int32(1)).(*int32),
    
    opened by kris-nova 16
  • TGIK: spotlight on naml

    TGIK: spotlight on naml

    Just wanted to say that I really like the project, writing (or templating) YAML is just painful!

    Also if anyone is interested, TGIK will be doing an episode showcasing naml on their Youtube channel in 2 days, it will be fun to watch :)

    https://youtu.be/ubJ4n_QHs98

    opened by Piotr1215 6
  • Codify fails when the input yaml object names have a dash in it.

    Codify fails when the input yaml object names have a dash in it.

    Took the example stateless app from https://kubernetes.io/docs/tasks/run-application/run-stateless-application-deployment/ and ran it against naml.

    [...]
    kind: Deployment
    metadata:
      name: nginx-deployment
    [...]
    

    Ran this through naml:

    kubectl get deployments -oyaml | naml c
    Error during codify: unable to auto format code: 88:2: expected identifier on left side of :=2021-08-01T18:41:03-07:00 [Critical  ]  unable to auto format code: 88:2: expected identifier on left side of :=
    

    I disabled gofmt to see the actual error and found this:

    nginx-deploymentDeployment := &appsv1.Deployment{
    

    We should probably trim illegal characters, though this may in rare circumstances cause a duplicate name. e.g. two deployments on the same system with names nginx-deployment vs nginxdeplolyment

    opened by fkautz 6
  • Make this a GitHub template repo?

    Make this a GitHub template repo?

    If I understand properly, you're supposed to fork this repo and then modify it to fit your app. GH templates would make it a little bit easier for folks to do that.

    opened by arschles 5
  • Codify doesn't deal well with unknown resource types

    Codify doesn't deal well with unknown resource types

    I tried running naml codify on an ObjectBucketClaim resource:

    apiVersion: objectbucket.io/v1alpha1
    kind: ObjectBucketClaim
    metadata:
      name: example-obc
    spec:
      generateBucketName: example-obc
      storageClassName: openshift-storage.noobaa.io
    

    I was expecting it to fail due to an unknown resource type, but to my surprise it didn't emit any errors. The resulting main.go has no resources (and does not compile).

    It would be nice if naml codify would emit an error (and fail) when it is unable to successfully convert the input.

    opened by larsks 4
  • Support MutatingWebhookConfiguration and HorizontalPodAutoscaler

    Support MutatingWebhookConfiguration and HorizontalPodAutoscaler

    This PR is largely motivated by the contents of https://github.com/knative/serving/releases/download/knative-v1.1.0/serving-core.yaml

    There are two issues that still require more work:

    1. Template delimiters inside configmap data causes parsing errors with go fmt. Not sure how to handle this at the moment so temporarily replaced double curly braces with quotes to get working output.
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: test
    data: 
      a: |
        # {{ .Name }}
    
    1. Handling multiple versions for a Horizontal Pod Autoscaler. v2beta2 was not replaced with autoscalingv2beta2 for some reason after the alias. Tried to follow policyv1beta1 but might've missed something. https://github.com/GuessWhoSamFoo/naml/blob/4194c5e2352317bfdd1709adf6a47140a0b503f2/codify/codify.go#L40
    opened by GuessWhoSamFoo 3
  • Compile Issue

    Compile Issue

    Saul Nachman12:17 PM
    # command-line-arguments
    ./test.go:31:2: imported and not used: "k8s.io/api/apps/v1" as appsv1
    ./test.go:32:2: imported and not used: "k8s.io/api/core/v1" as corev1
    ./test.go:33:2: imported and not used: "k8s.io/api/networking/v1" as networkingv1
    ./test.go:35:2: imported and not used: "k8s.io/apimachinery/pkg/util/intstr"
    ./test.go:73:25: undefined: Ingress
    ./test.go:108:33: client.NetworkingV1().Ingresss undefined (type "k8s.io/client-go/kubernetes/typed/networking/v1".NetworkingV1Interface has
    
    opened by kris-nova 3
  • use goname pattern in clusterrole

    use goname pattern in clusterrole

    ClusterRole now follows goname pattern that was set in Deployments.

    Also extracts goName into its own method for simplifcation.

    Signed-off-by: Frederick F. Kautz IV [email protected]

    opened by fkautz 3
  • not installing with different kubeconfig file

    not installing with different kubeconfig file

    Hi, really fun project, enjoying it so far :). One little thing I noticed; when I merge 2 kubeconfig files in the KUBECONFIG variable, there is hardcoded path searching for config file in .kube dir in this function in client.go

    // Client is used to authenticate with Kubernetes and build the Kube client
    // for the rest of the program.
    func Client() (*kubernetes.Clientset, error) {
    	kubeConfigPath := path.Join(homedir.HomeDir(), ".kube", "config")
    	return ClientFromPath(kubeConfigPath)
    }
    

    giving this error when context is in other file than config:

    unable to find local kube config [/home/decoder/.kube/config]: invalid configuration: [context was not found for specified context: default, cluster has no server defined]

    Swapping to another cluster (with context present in config) works as expected.

    Maybe reading KUBECONFIG variable on a retry when this error occurs would be a good idea?

    opened by Piotr1215 3
  • naml codify makefile

    naml codify makefile

    lets auto generate a makefile as well for our friends

    maybe syntax like this

    kubectl get deploy -oyaml | naml codify --name=beeps > main.go
    naml codify makefile --name=beeps > Makefile
    make
    ./beeps
    sudo make install
    beeps --help
    
    opened by kris-nova 2
  • Promote @fkautz to maintainer

    Promote @fkautz to maintainer

    This project seems to have seen decent traction - perhaps it's worth considering another maintainer?

    Anyway @fkautz you seem to be the most active here. Would you be interested in a low-commitment maintainer spot on the project to serve as another place to get things done / merge PRs / review my code / etc?

    opened by kris-nova 2
  • Errors when building generated main.go

    Errors when building generated main.go

    Dislaimer: I come from JavaLand. Applolgies if I am reporting something that would be easy to solve for people living in GoLand.

    I am trying out NAML to cofify an existing deployment

    1. I exported our deployment to yaml first via kubectl get all -n <my_namespace> -o yaml | tee out/all.yaml which resulted in a yaml file with 24031 lines
    2. Then I switched to the out folder and converted it to go via cat all.yaml | naml codify > main.go which resulted in a go file with 26986 lines
    3. Now that I tried go build main.go I am getting following errors
    > naml build -o app
    2022-04-25T11:14:16+02:00 [Warning   ]  ⚠ naml build alpha feature ⚠
    2022-04-25T11:14:16+02:00 [Warning   ]  if this is a feature you plan on using please make your use case known in the issue tracker
    2022-04-25T11:14:16+02:00 [Warning   ]  ⚠ naml build alpha feature ⚠
    2022-04-25T11:14:17+02:00 [Critical  ]  unable to build NAML binary from source: 
    
    +-------------------------+---------------------------------
    | Codify Compile Failure  |
    +-------------------------+
    | 
    | 
    | # command-line-arguments
    /tmp/3648555560.go:171:9: unknown field 'i' in struct literal of type resource.Quantity
    /tmp/3648555560.go:171:21: int64Amount not exported by package resource
    /tmp/3648555560.go:172:10: unknown field 'value' in struct literal of type resource.int64Amount
    /tmp/3648555560.go:173:10: unknown field 'scale' in struct literal of type resource.int64Amount
    /tmp/3648555560.go:175:9: unknown field 's' in struct literal of type resource.Quantity
    /tmp/3648555560.go:179:9: unknown field 'i' in struct literal of type resource.Quantity
    /tmp/3648555560.go:179:26: int64Amount not exported by package resource
    /tmp/3648555560.go:179:38: unknown field 'value' in struct literal of type resource.int64Amount
    /tmp/3648555560.go:180:9: unknown field 's' in struct literal of type resource.Quantity
    /tmp/3648555560.go:186:21: int64Amount not exported by package resource
    /tmp/3648555560.go:186:21: too many errors
    +----------------------------------------------------------
    

    Another thing that was quite strange to me was that NAML generated properties like NodeName: with the node a certain pod is currently running on. Haven't looked further but my gut feeling tells me that it generates code for pods resulting from staeful/daemon/replica-sets which doesn't feel right.

    opened by amalic 0
  • Use reflection and harden package names

    Use reflection and harden package names

    Relevant to #61 we can harden our package management

    We can (and should) use reflection to snoop the Kubernetes libraries as needed. We need to get rid of the string lists at the top of codify.go

    https://github.com/kris-nova/naml/blob/main/codify/codify.go#L37

    opened by kris-nova 0
  • naml build to solve for makefile and go.mod

    naml build to solve for makefile and go.mod

    Right now we have a problem with vendoring and capturing the compile commands with naml

    We can use naml build as a way to vet the code and ensure everything is working as expected

    opened by kris-nova 0
  • Failed to build result of

    Failed to build result of "naml codify"

    I have an example app that consists of a Service:

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: example
      name: example
    spec:
      ports:
      - port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: example
      type: LoadBalancer
    

    And a Deployment:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: example
      name: example
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: example
      template:
        metadata:
          labels:
            app: example
        spec:
          containers:
          - containerPorts:
            - containerPort: 8080
              name: http
              protocol: TCP
            image: alpinelinux/darkhttpd
            name: darkhttpd
    

    If I try to follow the instructions in the README, the build fails because of missing dependencies:

    $ mkdir out
    $ cat deployment.yaml service.yaml | naml codify > out/main.go
    $ cd out
    $ naml build -o app
    2021-11-21T08:15:27-05:00 [Critical  ]  unable to build NAML binary from source:
    
    +-------------------------+---------------------------------
    | Codify Compile Failure  |
    +-------------------------+
    |
    |
    | /tmp/3696928851.go:34:2: no required module provides package github.com/kris-nova/naml: go.mod file not found in current directory or any parent directory; see 'go help modules'
    /tmp/3696928851.go:30:2: no required module provides package k8s.io/api/core/v1: go.mod file not found in current directory or any parent directory; see 'go help modules'
    /tmp/3696928851.go:31:2: no required module provides package k8s.io/apimachinery/pkg/apis/meta/v1: go.mod file not found in current directory or any parent directory; see 'go help modules'
    /tmp/3696928851.go:35:2: no required module provides package k8s.io/apimachinery/pkg/runtime: go.mod file not found in current directory or any parent directory; see 'go help modules'
    /tmp/3696928851.go:32:2: no required module provides package k8s.io/apimachinery/pkg/util/intstr: go.mod file not found in current directory or any parent directory; see 'go help modules'
    /tmp/3696928851.go:36:2: no required module provides package k8s.io/client-go/kubernetes: go.mod file not found in current directory or any parent directory; see 'go help modules'
    

    If I try to resolve the dependency problems by running go mod init and go tidy...

    $ go mod init example
    go: creating new go.mod: module example
    go: to add module requirements and sums:
            go mod tidy
    $ go mod tidy
    go: finding module for package github.com/kris-nova/naml
    go: finding module for package k8s.io/api/core/v1
    go: finding module for package k8s.io/apimachinery/pkg/apis/meta/v1
    go: finding module for package k8s.io/apimachinery/pkg/util/intstr
    go: finding module for package k8s.io/client-go/kubernetes
    go: finding module for package k8s.io/apimachinery/pkg/runtime
    go: found github.com/kris-nova/naml in github.com/kris-nova/naml v1.0.1
    go: found k8s.io/api/core/v1 in k8s.io/api v0.22.4
    go: found k8s.io/apimachinery/pkg/apis/meta/v1 in k8s.io/apimachinery v0.22.4
    go: found k8s.io/apimachinery/pkg/runtime in k8s.io/apimachinery v0.22.4
    go: found k8s.io/apimachinery/pkg/util/intstr in k8s.io/apimachinery v0.22.4
    go: found k8s.io/client-go/kubernetes in k8s.io/client-go v0.22.4
    

    ...and then attempt to build, it fails with unused imports and an undefined reference:

    $ naml build -o app
    2021-11-21T08:16:51-05:00 [Critical  ]  unable to build NAML binary from source:
    
    +-------------------------+---------------------------------
    | Codify Compile Failure  |
    +-------------------------+
    |
    |
    | # command-line-arguments
    /tmp/2642747543.go:30:2: imported and not used: "k8s.io/api/core/v1" as corev1
    /tmp/2642747543.go:32:2: imported and not used: "k8s.io/apimachinery/pkg/util/intstr"
    /tmp/2642747543.go:70:21: undefined: Service
    +----------------------------------------------------------
    

    Is the README missing some steps? Am I missing some steps?

    I am using naml 1.0.1.

    opened by larsks 7
  • codify: replace valast.Addr(v).(*T) with k8s.io/utils/pointer equivalents?

    codify: replace valast.Addr(v).(*T) with k8s.io/utils/pointer equivalents?

    πŸ‘‹πŸ» Firstly, thank you so much for naml β€” it is wonderful!


    It would be great if the codify-generated code could avoid the runtime dependency on valast by using the k8s.io/utils/pointer package for getting pointers to a primitive:

    e.g.,

    -valast.Addr(false).(*bool)
    +pointer.Bool(false)
    -valast.Addr(int64(65534)).(*int64)
    +pointer.Int64(65534)
    

    etc.

    This also produces more readable code.

    Obviously there's no built-in support in valast for customising the generated ast so it would have to be a post-processing task done in codify itself

    opened by dnwe 1
Releases(v1.0.3)
Owner
Kris NΓ³va
professional grown up business adult does important internet business
Kris NΓ³va
How you can use Go to replace YAML files with Kubernetes.

YamYams A small project that is free to use. ?? I wanted to offer a starting point for anyone interested in replacing YAML with Go. You can read more

Kris NΓ³va 1.1k Jun 25, 2022
kubectl plugin for signing Kubernetes manifest YAML files with sigstore

k8s-manifest-sigstore kubectl plugin for signing Kubernetes manifest YAML files with sigstore ⚠️ Still under developement, not ready for production us

sigstore 29 Jun 18, 2022
YAML and Golang implementations of common Kubernetes patterns.

Kubernetes Patterns Types Patterns Foundational Patterns Behavioral Patterns Structural Patterns Configuration Patterns Usage To run, simply do go run

Sharad Bhat 70 Apr 12, 2022
Creates Helm chart from Kubernetes yaml

Helmify CLI that creates Helm charts from kubernetes yamls. Helmify reads a list of supported k8s objects from stdin and converts it to a helm chart.

Artem 255 Jul 4, 2022
Just a dummy Kubernetes Operator, playing with another dummy service

My first operator Just playing/learning to create a K8S operator in go. I will create a dummy operator that creates pods to open a shell inside It is

Jose Gato Luis 0 Dec 16, 2021
Kubernetes OS Server - Kubernetes Extension API server exposing OS configuration like sysctl via Kubernetes API

KOSS is a Extension API Server which exposes OS properties and functionality using Kubernetes API, so it can be accessed using e.g. kubectl. At the moment this is highly experimental and only managing sysctl is supported. To make things actually usable, you must run KOSS binary as root on the machine you will be managing.

Mateusz Gozdek 3 May 19, 2021
An Easy to use Go framework for Kubernetes based on kubernetes/client-go

k8devel An Easy to use Go framework for Kubernetes based on kubernetes/client-go, see examples dir for a quick start. How to test it ? Download the mo

null 10 Mar 25, 2022
General Pod Autoscaler(GPA) is a extension for K8s HPA, which can be used not only for serving, also for game.

Introduction General Pod Autoscaler(GPA) is a extension for K8s HPA, which can be used not only for serving, also for game. Features Compatible with a

Open Cloud-native Game-application Initiative 13 Jun 27, 2022
Write controller-runtime based k8s controllers that read/write to git, not k8s

Git Backed Controller The basic idea is to write a k8s controller that runs against git and not k8s apiserver. So the controller is reading and writin

Darren Shepherd 50 Dec 10, 2021
Pulumi provider for Vultr (based on the Terraform one), not official

Vultr Resource Provider The Vultr Resource Provider lets you manage Vultr resources. Installing This package is currently not available for most langu

Vincent Bernat 2 Apr 23, 2022
Demo of skaffold's port-forwarding with ko builder (does not work)

skaffold port-forwarding : Ko builder vs docker builder When using ko builder (see folder ko/), port forwarding does not work (skaffold debug or skaff

null 0 Jan 6, 2022
An operator which complements grafana-operator for custom features which are not feasible to be merged into core operator

Grafana Complementary Operator A grafana which complements grafana-operator for custom features which are not feasible to be merged into core operator

Snapp Cab Incubators 4 May 24, 2022
This is for managing Slack App Manifests, it is no use if you are not developing an App for Slack.

Terraform Provider Slack App This is for managing Slack App Manifests, it is no use if you are not developing an App for Slack. Requirements Terraform

ChangeEngine 2 May 23, 2022
Β΅Task is an automation engine that models and executes business processes declared in yaml. βœοΈπŸ“‹

Β΅Task, the Lightweight Automation Engine Β΅Task is an automation engine built for the cloud. It is: simple to operate: only a postgres DB is required s

OVHcloud 669 Jun 30, 2022
Converts your k8s YAML to a cdk8s Api Object.

kube2cdk8s Converts your k8s YAML to a cdk8s Api Object. Uses Pulumi's kube2pulumi as a base. Dependencies 1. pulumi cli 2. pulumi kubernetes provider

smallcase 11 Jun 28, 2022
No YAML deployments to K8s

no-yaml No YAML deployments to K8s with following approaches: Pulumi NAML cdk8s We will deploy the ?? ?? CNCF App Delivery SIG Demo podtato-head and u

Engin Diri 11 Apr 26, 2022
A handy utility to generate configmap and values.yaml of your application for helmifying them

Helmfig Are you tired of writing values.yaml for configmap of your project when you are helmifying them? Helmfig is a handy tool that can generate the

Snapp Cab Incubators 23 Jun 1, 2022
go-opa-validate is an open-source lib that evaluates OPA (open policy agent) policy against JSON or YAML data.

go-opa-validate go-opa-validate is an open-source lib that evaluates OPA (open policy agent) policy against JSON or YAML data. Installation Usage Cont

chenk 5 Feb 5, 2022
Prestic - Lets you define and run restic commands from a YAML file

Pete's Restic Lets you define and run restic commands from a YAML file. Features

Pete Taylor 0 Jan 10, 2022