Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

kable-logo

Kable

GoReleaseLicense

A tool to manage kubernetes resources in a GitOps fashion.

It reads so-called "concepts" (see terminology), and renders them into various deployable formats. (YAML Manifests, GitOps controller instructions, helm charts, etc.)

Install

Download the binaries from Releases, and install to a directory on your path.

macOS

brew tap redradrat/kable
brew install kable

Getting Started

You want to manage your kubernetes resources with kable? Great!

Here is a quick primer:

  • Kable essentially is a tool to manage so-called concepts and the repos they reside in.
  • A concept is a directory, containing a concept.json and "source", defining Kubernetes resources.
  • A repo is a git repository, containing concepts.
  • Rendering is the process of "instantiating" a concept, resulting in various deployable formats.

First we want to add an existing concept repository:

~/Development/getting-started ❯ kable repo add demo https://github.com/redradrat/demo-concepts.git
Fetching repository...
? Does this repository require basic authentication? N
✔ Successfully added repository!

There you go! We've added our first repository! What can we do with that?

A repository contains various concepts that are ready to be rendered by us. To list our available concepts, we can use the kable list command.

~/Development/getting-started ❯ kable list
ID | REPOSITORY | MAINTAINER ---------------+------------+-------------------------------------------
apps/grafana | demo | Name <email> apps/sentry | demo | Name <email> 

As you can see, there are some concepts already available in the repository. Why not head over there and check it out?

Now let's actually render one of these into a format that we can actually apply to our k8s cluster. With kable render we can do so! This command has quite a few tricks up its sleeve. So be sure to check out what you can do with kable render --help.

For now let's use kable render apps/grafana@demo -o out/:

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) [? for help] 

As this is our first time rendering this, a dialog will open up, asking us for values. So for now we will comply with what this pesky dialog wants.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml
Fetching Concept 'apps/grafana@demo'...
Mandatory Values
? instanceName (string) test
? nameSelection Option 1
Rendering concept...
✔ Successfully created concept!

Alright! Let's see what we got, shall we? The -o flag we used, defined an output directory out/ for kable to write to.

~/Development/getting-started ❯ tree out out
├── apps-v1_Deployment_test.yaml
├── renderinfo.json
└── v1_Service_test.yaml

Apparently our concept consists of multiple k8s resources. A separate manifest has been created for each. You can change this behavior by using -s, which will render all resources into a single manifest, manifest.yaml.

Notice the renderinfo.json file? This file contains the information of how this rendering has been created. On subsequent render runs, the values we initially provided will be reused, if this file is detected. You can even pass a specific file with -r!

~/Development/getting-started ❯ bat out/renderinfo.json ───────┬────────────────────────────────────────────────────────────────────
│ File: out/renderinfo.json
───────┼────────────────────────────────────────────────────────────────────
1 │ {
2 │ "version": 1,
3 │ "meta": {
4 │ "date": "17 Oct 20 17:42 CEST"
5 │ },
6 │ "origin": {
7 │ "repository": "https://github.com/redradrat/demo-concepts",
8 │ "ref": "refs/heads/master"
9 │ },
10 │ "values": {
11 │ "instanceName": "test",
12 │ "nameSelection": "Option 1"
13 │ }
14 │ }
───────┴────────────────────────────────────────────────────────────────────

When we now run our render command again, we will see that kable automatically detects the renderinfo.json file in the output path, and reuses it's values.

~/Development/getting-started ❯ kable render apps/grafana@demo -o out/ -t yaml Fetching Concept 'apps/grafana@demo'...
Rendering concept...
✔ Successfully created concept!

See? No pesky dialog this time!

Whenever kable auto-detects a renderinfo.json in the output path, or if we pass an existing one via -r path/to/renderinfo.json, the dialog will not appear.

That's it! You're now able to render and use concepts! Make sure to check out the development section to take a deeper look at how to write concepts.

Usage

~ ❯ kable Usage:
[command]
Available Commands:
helm Tools to interact with helm
help Help about any command
init Initialize a concept in the current folder
list List all available concepts
render Render a concept
repo Add/List/Remove concept repositories for kable
serve Run kable as a server
version Show version information
Flags:
-h, --help help for this command
Use " [command] --help" for more information about a command.

Terminology

Concept

A concept is a blueprint of an app. It is written in a specific language can be rendered to various outputs.

Supported Types:

  • Jsonnet
  • JavaScript/Typescript (upcoming)

A concept defines a specific set of inputs, that are passed on to the underlying type. (jsonnet, javascript, etc.)

Each concept needs to build on its own, that's why there is no dependency concept in kable. If let's say a Jsonnet concept depends on another Jsonnet concept, this should be realized via the Jsonnet-specific package management.

Example:

demo-concepts/apps/grafana ❯ tree
.
├── Makefile
├── concept.json
├── jsonnetfile.json
├── lib
│ ├── k.libsonnet
│ └── main.libsonnet
├── main.jsonnet
└── vendor

Concept File

What makes a regular directory a concept, is a concept.json file at its root. It describes:

  • metadata - Name and maintainer of the Concept
  • type - The concept type tells kable what the actual content is. Jsonnet? Javascript?
  • inputs - See inputs.

Inputs

Inputs are a core aspect of any concept. They define a set of required or optional values, that are needed to render the underlying definiton.

When rendering via kable render a dialog will ask the user about the defined inputs.

Types:

  • string
  • int
  • bool
  • map
  • select

concept.json

Examples of how to define aforementioned inputs in your concept.json file:

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {...},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string"
},
"int": {
"type": "int"
},
"bool": {
"type": "bool"
},
"map": {
"type": "map"
},
"selection": {
"type": "select",
"options": [
"Option 1",
"Option 2"
]
}
},
"optional": {
// ANOTHER SECTION OF INPUTS THAT ARE NOT MANDATORY"string": {
"type": "string"
},
...
}
}
}

There is the possibility to add a description and example to each required input.

{
"apiVersion": 1,
"type": "jsonnet",
"metadata": {
...
},
"inputs": {
"mandatory": {
// HERE WE CAN DEFINE INPUTS"string": {
"type": "string",
"description": "This text describes the purpose of the input.",
"example": "examplevalue"
},
...
}
}
}

Repo

Repos are git repositories that contain multiple concepts. They are used as a platform for exchange of concepts, and to render concepts from.

Crucially, they contain a kable.json file at their root, listing all the concepts contained within.

Example kable.json:

{
"version": 1,
"concepts": [
"apps/grafana",
"apps/sentry"
]
}

A local kable installation can configure multiple repositories at the same time.

Demo Repository

A demo repository can be found at https://github.com/redradrat/demo-concepts

kable repo add demo https://github.com/redradrat/demo-concepts.git

Render

Rendering, means to instantiate a concept. It's "Application" so to say. Multiple output targets supported.

Supported Targets:

  • YAML
  • FluxCD Application (upcoming)
  • Kable Application (upcoming)

Rendering a concept will give the user a dialog, helping users to define their input values. These values will be stored in the renderinfo.json file. On consecutive render interactions, and pointing kable to this file, those values will be reused.

Development

TBD

Thanks

  • grafana/tanka - For sticking to jsonnet and maintaining an amazing project. Kable relies on their yaml rendering "engine" including the amazing Helmraiser 😎🔥.

About

Manage kubernetes resources - GitOps galore!

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages