Skip to content

Commit

Permalink
feat: release 0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pr0ton11 committed Jun 28, 2024
1 parent 6fea553 commit 717a287
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 0 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Build and publish image
on:
push:
branches:
- main

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push-image:
runs-on: ubuntu-latest
defaults:
run:
working-directory: './app'

steps:
- uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GH_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM docker.io/golang:1.22.0

LABEL org.opencontainers.image.title=ceph-cft
LABEL org.opencontainers.image.description="Configure your ceph cluster with environment variables"
LABEL org.opencontainers.image.version=0.1.0
LABEL org.opencontainers.image.licenses=GPL-3.0
LABEL org.opencontainers.image.url=https://github.com/pr0ton11/ceph-cft
LABEL org.opencontainers.image.source=https://github.com/pr0ton11/ceph-cft
LABEL org.opencontainers.image.authors=pr0ton11

ENV CGO_ENABLED=0
ENV GOOS=linux

COPY . /app

WORKDIR /app

RUN go mod download && go build -ldflags="-s -w" -o /app/ceph-cft
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Ceph Config Format Tool

This tool allows to configure your Ceph cluster simply by defining environment variables prefixed with *CEPH_*

Uses restrictions of https://docs.ceph.com/en/latest/rados/configuration/ceph-conf

## How does it work?

It iterates through the defined environment variables and:

* Detects if a variable if prefixed with Ceph
* Contains a valid configuration section (default: global)
* Supports fine grained configuration of specific individual daemons (e.g client.1) by replacing *__* with *.*
* Writes the updated ceph configuration file

## How do I use it

Just run ceph-cft before you start your ceph daemons and it will update / override the configuration values in ceph.conf based on environment variables.

## How do I define a custom path to ceph.conf?

This can be accomplished by setting the environment variable ``` CFT_CONFIG_PATH ```. Default is ```/etc/ceph/ceph.conf```.

## Examples

The following environment variables were set:

```
CEPH_GLOBAL_LOG_FILE='/var/log/ceph/$cluster-$type.$id.log'
CEPH_OSD_OP_QUEUE=wpq
CEPH_MON_LOG_TO_SYSLOG=true
CEPH_TEST_WITHOUT_SECTION=works
CEPH_CONTAINS_WHITESPACES="Hello World"
CEPH_OSD__1_OBJECTER_INFLIGHT_OPS=512
```

This leads to the generation of the following configuration file:

```
[global]
log_file = /var/log/ceph/$cluster-$type.$id.log
test_without_section = works
contains_whitespaces = "hello world"
[osd]
op_queue = wpq
[mon]
log_to_syslog = true
[osd.1]
objecter_inflight_ops = 512
```


## Where is it used

This tool is used for the following projects:

* https://github.com/pr0ton11/radosgw
* https://github.com/pr0ton11/ceph-yocto
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/pr0ton11/ceph-cft

go 1.22.4

require gopkg.in/ini.v1 v1.67.0 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
97 changes: 97 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package main

import (
"log"
"os"
"strings"

"gopkg.in/ini.v1"
)

// Allowed section prefixes in the configuration file
var ALLOWED_SECTION_PREFIX []string = []string{"global", "mon", "mgr", "osd", "mds", "client"}

// This application is a simple utility to manage the Ceph configuration file by defining configuration values as environment variables.
// The application will load the current configuration file, update the values based on the environment variables, and write the updated configuration file.
// Format of the environment variables: CEPH_{SECTION}_{KEY}={VALUE}
// Example: CEPH_GLOBAL_CLUSTER_NETWORK=10.0.0.0/24
// If the section is not defined, the application will use the default section (GLOBAL).

func main() {
// Retrieve the configuration path
configPath, ok := os.LookupEnv("CFT_CONFIG_PATH")
// Otherwise, use the default path to the configuration file
if !ok {
configPath = "/etc/ceph/ceph.conf"
}

// Load the current configuration
current, err := ini.Load(configPath)
if err != nil {
log.Printf("Error loading the current configuration file %s: %v", configPath, err)
current = ini.Empty()
}

// Iterate over the environment variables
for _, env := range os.Environ() {
// Workaround for the issue that dots are not allowed in environment variables
// Replace the double underscore with a dot
env = strings.Replace(env, "__", ".", -1)
// Convert the environment variable to lower case for simplicity
env = strings.ToLower(env)
// Split the environment variable into key and value
assignment := strings.Split(env, "=")
// Assign the key
key := assignment[0]
// Assign the value
value := assignment[1]

// Check if the environment variable is a ceph configuration variable
if strings.HasPrefix(key, "ceph_") {
log.Printf("Found key: %s with value: %s", key, value)
// Split the key further into section and configuration key
keyParts := strings.Split(key, "_")
// Set flag to detect if the section is defined
sectionDetected := false
// Check if the section is defined
detectedSection := "global"
// Only allow prefixes if they are defined in the allowed section prefixes
for _, section := range ALLOWED_SECTION_PREFIX {
if strings.HasPrefix(keyParts[1], section) {
sectionDetected = true
detectedSection = keyParts[1]
}
}
// Output a warning if the section is not defined
if !sectionDetected {
log.Printf("No section deteced in key %s, using default %s", key, detectedSection)
} else {
log.Printf("Detected section: %s for key %s", detectedSection, key)
}
// Cleanup the key by removing both the prefix and the section if defined
if sectionDetected {
key = strings.Join(keyParts[2:], "_")
} else {
key = strings.Join(keyParts[1:], "_")
}

// If the value contains a space, wrap it in quotes
if strings.Contains(value, " ") {
if !strings.HasPrefix(value, "\"") && !strings.HasSuffix(value, "\"") {
value = "\"" + value + "\""
}
}

// Update the configuration
log.Printf("Setting key: %s with value: %s in section: %s", key, value, detectedSection)
current.Section(detectedSection).Key(key).SetValue(value)
}

// Write the updated configuration
err = current.SaveTo(configPath)
if err != nil {
log.Printf("Error saving the updated configuration file %s: %v", configPath, err)
}
}

}

0 comments on commit 717a287

Please sign in to comment.