Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project Template #18

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 184 additions & 0 deletions pkg/template/example/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
{
"id": "example1",
"name": "my-awesome-php-app",
"description": "Example PHP application with PostgreSQL database",
"buildConfigs": [
{
"name": "mfojtik/nginx-php-app",
"type": "docker",
"sourceUri": "https://raw.githubusercontent.com/mfojtik/phpapp/master/Dockerfile",
"imageRepository": "mfojtik/nginx-php-app"
},
{
"name": "postgres",
"type": "docker",
"sourceUri": "https://raw.githubusercontent.com/docker-library/postgres/docker/9.2/Dockerfile",
"imageRepository": "postgres"
}
],
"imageRepositories": [
{
"name": "mfojtik/nginx-php-app",
"url": "internal.registry.com:5000/mfojtik/phpapp"
},
{
"name": "postgres",
"url": "registry.hub.docker.com/postgres"
}
],
"parameters": [
{
"name": "DB_PASSWORD",
"description": "PostgreSQL admin user password",
"type": "string",
"generate": "[a-zA-Z0-9]{8}"
},
{
"name": "DB_USER",
"description": "PostgreSQL username",
"type": "string",
"generate": "admin[a-zA-Z0-9]{4}"
},
{
"name": "DB_NAME",
"description": "PostgreSQL database name",
"type": "string",
"value": "mydb"
},
{
"name": "REMOTE_KEY",
"description": "Example of remote key",
"type": "string",
"value": "[GET:http://custom.url.int]"
}
],
"services": [
{
"id": "database",
"kind": "Service",
"apiVersion": "v1beta1",
"port": 5432,
"selector": {
"name": "database"
}
},
{
"id": "frontend",
"kind": "Service",
"apiVersion": "v1beta1",
"port": 8080,
"selector": {
"name": "frontend"
}
}
],
"deploymentConfigs": [
{
"kind": "DeploymentConfig",
"apiVersion": "v1beta1",
"labels": {
"name": "database"
},
"desiredState": {
"replicas": 2,
"replicaSelector": {
"name": "database"
},
"podTemplate": {
"kind": "Pod",
"apiVersion": "v1beta1",
"id": "database",
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "database",
"containers": [{
"name": "postgresql",
"image": "postgres",
"env": [
{
"name": "PGPASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "PGUSER",
"value": "${DB_USER}"
},
{
"name": "PGDATABASE",
"value": "${DB_NAME}"
},
{
"name": "FOO",
"value": "${BAR}"
}
],
"ports": [
{
"containerPort": 5432
}
]
}
]
}
},
"labels": {
"name": "database"
}
}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1beta1",
"labels": {
"name": "frontend"
},
"desiredState": {
"replicas": 2,
"replicaSelector": {
"name": "frontend"
},
"podTemplate": {
"kind": "Pod",
"apiVersion": "v1beta1",
"id": "frontend",
"desiredState": {
"manifest": {
"version": "v1beta1",
"id": "frontend",
"containers": [{
"name": "frontend",
"image": "mfojtik/nginx-php-app",
"env": [
{
"name": "PGPASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "PGUSER",
"value": "${DB_USER}"
},
{
"name": "PGDATABASE",
"value": "${DB_NAME}"
}
],
"ports": [
{
"containerPort": 9292,
"hostPort": 8080
}
]
}
]
}
},
"labels": {
"name": "frontend"
}
}
}
}
]
}
89 changes: 89 additions & 0 deletions pkg/template/example/simple.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"id": "example2",
"name": "my-awesome-php-app",
"description": "Example PHP application with PostgreSQL database",
"parameters": [
{
"name": "DB_PASSWORD",
"description": "PostgreSQL admin user password",
"type": "string",
"generate": "[a-zA-Z0-9]{8}"
},
{
"name": "DB_USER",
"description": "PostgreSQL username",
"type": "string",
"generate": "admin[a-zA-Z0-9]{4}"
},
{
"name": "SAMPLE_VAR",
"description": "Sample",
"type": "string",
"value": "foo"
}
],
"serviceLinks": [
{
"from": "database",
"export": [
{
"name": "POSTGRES_ADMIN_USERNAME",
"value": "${DB_USER}"
},
{
"name": "POSTGRES_ADMIN_PASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "POSTGRES_DATABASE_NAME",
"value": "${DB_NAME}"
}
],
"to": "frontend"
}
],
"services": [
{
"name": "database",
"description": "Standalone PostgreSQL 9.2 database service",
"labels": {
"name": "database-service"
},
"deploymentConfig": {
"deployment": {
"podTemplate": {
"containers": [
{
"name": "postgresql-1",
"image": {
"name": "postgres",
"tag": "9.2"
},
"env": [
{
"name": "POSTGRES_ADMIN_USERNAME",
"value": "${DB_USER}"
},
{
"name": "POSTGRES_ADMIN_PASSWORD",
"value": "${DB_PASSWORD}"
},
{
"name": "FOO",
"value": "${CUSTOM_PARAM1}"
}
],
"ports": [
{
"containerPort": 5432,
"hostPort": 5432
}
]
}
]
}
}
}
}
]
}
39 changes: 39 additions & 0 deletions pkg/template/generator/generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package generator

import (
"fmt"
"math/rand"
"net/http"
)

type GeneratorType interface {
Value() (string, error)
}

type PasswordGenerator struct {
length int
}

func (g PasswordGenerator) Value() (string, error) {
return Template{Expression: fmt.Sprintf("[\\a]{%d}", g.length)}.Value()
}

type Generator struct {
seed *rand.Rand
}

func (g *Generator) SetSeed(r *rand.Rand) {
g.seed = r
}

func (g Generator) Generate(t string) GeneratorType {
if g.seed == nil {
return nil
}
switch t {
case "password":
return PasswordGenerator{length: 8}
default:
return Template{Expression: t, HttpClient: &http.Client{}, seed: g.seed}
}
}
78 changes: 78 additions & 0 deletions pkg/template/generator/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package generator

import (
"fmt"
"math/rand"
"strconv"
"strings"
)

func alphabetSlice(from, to byte) (string, error) {
leftPos := strings.Index(Ascii, string(from))
rightPos := strings.LastIndex(Ascii, string(to))
if leftPos > rightPos {
return "", fmt.Errorf("Invalid range specified: %s-%s", string(from), string(to))
}
return Ascii[leftPos:rightPos], nil
}

func replaceWithGenerated(s *string, expresion string, ranges [][]byte, length int, seed *rand.Rand) error {
var alphabet string
for _, r := range ranges {
switch string(r[0]) + string(r[1]) {
case `\w`:
alphabet += Ascii
case `\d`:
alphabet += Numerals
case `\a`:
alphabet += Alphabet + Numerals
default:
if slice, err := alphabetSlice(r[0], r[1]); err != nil {
return err
} else {
alphabet += slice
}
}
}
if len(alphabet) == 0 {
return fmt.Errorf("Empty range in expresion: %s", expresion)
}
result := make([]byte, length, length)
for i := 0; i <= length-1; i++ {
result[i] = alphabet[seed.Intn(len(alphabet))]
}
*s = strings.Replace(*s, expresion, string(result), 1)
return nil
}

func findExpresionPos(s string) GeneratorExprRanges {
matches := rangeExp.FindAllStringIndex(s, -1)
result := make(GeneratorExprRanges, len(matches), len(matches))
for i, r := range matches {
result[i] = []byte{s[r[0]], s[r[1]-1]}
}
return result
}

func rangesAndLength(s string) (string, int, error) {
l := strings.LastIndex(s, "{")
// If the length ({}) is not specified in expresion,
// then assume the length is 1 character
//
if l > 0 {
expr := s[0:strings.LastIndex(s, "{")]
length, err := parseLength(s)
return expr, length, err
} else {
return s, 1, nil
}
}

func parseLength(s string) (int, error) {
lengthStr := string(s[strings.LastIndex(s, "{")+1 : len(s)-1])
if l, err := strconv.Atoi(lengthStr); err != nil {
return 0, fmt.Errorf("Unable to parse length from %v", s)
} else {
return l, nil
}
}
Loading