Add Behave BDD Tests and Swagger Docs
All checks were successful
continuous-integration/drone/push Build is passing

* Added Behave BDD Tests for User Service
* Added Swagger Docs for User Service
* Added Vault, Redpanda helm config (not yet being used)
* Added frontend config for host / port when running locally
This commit is contained in:
2022-05-19 09:24:31 -03:00
parent 14c72e3745
commit a5ad4341cf
83 changed files with 19847 additions and 7949 deletions

3
.gitignore vendored
View File

@@ -12,4 +12,5 @@ Cargo.lock
.helm
.idea
tilt_modules/
helm/**/charts/
helm/**/charts/
.python-version

View File

@@ -4,9 +4,9 @@ RUN apt update && apt install -y \
iputils-ping \
libpq-dev
RUN cd /tmp \
&& wget http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.33-0ubuntu5_amd64.deb \
&& dpkg -i libc6_2.33-0ubuntu5_amd64.deb \
&& rm libc6_2.33-0ubuntu5_amd64.deb
&& wget http://ftp.us.debian.org/debian/pool/main/g/glibc/libc6_2.34-0experimental4_amd64.deb \
&& dpkg -i libc6_2.34-0experimental4_amd64.deb \
&& rm libc6_2.34-0experimental4_amd64.deb
ARG binary_location
ARG binary_name
COPY $binary_location /bin/$binary_name

View File

@@ -10,4 +10,5 @@ cargo-build:
# # Set Git Config for Git Hooks
# ----------------------------------------
hooks:
$(shell git config --local core.hooksPath .githooks)
$(shell git config --local core.hooksPath .githooks)# ----------------------------------------

View File

@@ -3,6 +3,7 @@
###################################################################################################
#
###################################################################################################
local_resource(
'cargo-build',
'make cargo-build',
@@ -12,19 +13,23 @@ local_resource(
###################################################################################################
#
###################################################################################################
local_resource(
'update-helm',
'helm repo add bitnami https://charts.bitnami.com/bitnami \
&& helm repo add hashicorp https://helm.releases.hashicorp.com \
# && helm repo add redpanda https://charts.vectorized.io \
# && helm repo add jetstack https://charts.jetstack.io \
&& for d in helm/*; do [[ -f "$d"/Chart.yaml ]] && helm dependency update $d; done',
auto_init=False,
trigger_mode=TRIGGER_MODE_MANUAL,
#auto_init=False,
#trigger_mode=TRIGGER_MODE_MANUAL,
labels=['Build']
)
###################################################################################################
# API GATEWAY
###################################################################################################
local_resource(
'pack-api-gateway',
'eval $(minikube docker-env) \
@@ -50,6 +55,7 @@ k8s_resource(
###################################################################################################
# User Service
###################################################################################################
local_resource(
'pack-user-service',
'eval $(minikube docker-env) \
@@ -72,6 +78,7 @@ k8s_resource(
###################################################################################################
# Consumer
###################################################################################################
local_resource(
'pack-consumer',
'eval $(minikube docker-env) \
@@ -94,6 +101,7 @@ k8s_resource(
###################################################################################################
# Producer
###################################################################################################
local_resource(
'pack-producer',
'eval $(minikube docker-env) \
@@ -113,10 +121,10 @@ k8s_resource(
labels=['Core_Services']
)
###################################################################################################
# PostgreSQL
###################################################################################################
k8s_yaml(helm(
'./helm/postgresql',
name='postgresql',
@@ -138,6 +146,7 @@ k8s_resource(
###################################################################################################
# RaabitMQ
###################################################################################################
k8s_yaml(helm(
'./helm/rabbitmq',
name='rabbitmq',
@@ -157,9 +166,32 @@ k8s_resource(
labels=['RabbitMQ']
)
###################################################################################################
# Vault
###################################################################################################
k8s_yaml(helm(
'./helm/vault',
name='vault',
values=[
'helm/vault/values.yaml'
]
))
k8s_resource(
workload='vault',
resource_deps=[
'update-helm',
],
port_forwards=[
port_forward(8200, 8200, name='Vault Port'),
],
labels=['Vault']
)
###################################################################################################
# Frontend
###################################################################################################
local_resource(
'build-frontend',
'rm -rf frontend/build \
@@ -187,6 +219,55 @@ k8s_resource(
labels=['Frontend']
)
###################################################################################################
# Swagger
###################################################################################################
local_resource(
'update-swagger-doc',
# This is hacky... try to do something better
'if [ ! -z "$(kubectl get pods | grep swagger)" ]; then kubectl delete configmap vol-cfg-swaggerdoc && kubectl create configmap vol-cfg-swaggerdoc --from-file=helm/swagger/spec/swagger.yaml && kubectl delete pod $(kubectl get pods | grep swagger | cut -d " " -f 1); fi',
deps=[
'./helm/swagger/spec/swagger.yaml',
'./crates/api-gateway/doc/swagger.yaml'
],
labels=['Docs'],
)
k8s_yaml(helm(
'./helm/swagger',
name='swagger',
values=[
'helm/swagger/values.yaml'
]
))
k8s_resource(
workload='swagger',
port_forwards=[
port_forward(8081, 8080, name='Swagger'),
],
resource_deps=[
'update-swagger-doc',
],
labels=['Docs']
)
###################################################################################################
# Redpanda
###################################################################################################
#k8s_yaml(helm(
# './helm/redpanda',
# name='redpanda',
# values=[
# 'helm/redpanda/values.yaml'
# ]
#))
#k8s_resource(
# workload='redpanda-redpanda-operator',
# labels=['Redpanda']
#)
###################################################################################################
# END
###################################################################################################

63
bin/README.md Normal file
View File

@@ -0,0 +1,63 @@
# cert-manager-verifier
Helps you properly wait for [cert-manager](https://github.com/jetstack/cert-manager) installation to be ready to use.
All versions of cert-manager are supported down to 0.12.
## Motivation
Pretty much every kubernetes installation nowadays depends on cert-manager for certificate provisioning. But at the same time, I've seen a lot of flakiness in several projects that were caused by inproperly implemented wait on cert-manager to be ready.
Currently the right way to do this is documented in [installation guide](https://cert-manager.io/docs/installation/kubernetes/#verifying-the-installation). It consists of several steps and typically in a CI or automated environment, you don't want to execute those manually and that's where this project aims to help.
## Usage
There are two ways how to use the verifier - CLI and as a go library and your choice depends on what your cluster installation tooling looks like.
### CLI integration
The CLI is just another binary you call from your CI/CD pipeline or cluster installation scripts. When it returns exitcode 0 you know cert-manager is ready to use.
It expects kubeconfig/user that is allowed to create namespace in the default settings (it creates and cleans up cert-manager-test ns to deploy the test certificates). See `cm-verifier --help` for more information about how to configure this.
```shell script
./cm-verifier
Waiting for following deployments in namespace cert-manager:
- cert-manager
- cert-manager-cainjector
- cert-manager-webhook
Deployment cert-manager READY! ヽ(•‿•)
Deployment cert-manager-cainjector READY! ヽ(•‿•)
Deployment cert-manager-webhook READY! ヽ(•‿•)
Resource cert-manager-test created
Resource test-selfsigned created
Resource selfsigned-cert created
ヽ(•‿•) Cert-manager is READY!%
```
You can configure what the CLI does via flags:
```
--debug 'print out debug logs as well'
--namespace 'namespace into which cert-manager is installed'
--timeout 'set timeout after which we give up waiting for cert-manager'
```
### As a library
For a full example see [examples/main.go](examples/main.go)
```
import "github.com/alenkacz/cert-manager-verifier/pkg/verify"
...
result, err := verify.Verify(ctx, config, &verify.Options{CertManagerNamespace: "cert-manager"})
if err != nil {
log.Fatal(err)
}
if result.Success {
fmt.Println("Success!!!")
} else {
fmt.Println("Failure :-(")
}
```

BIN
bin/cm-verifier Executable file

Binary file not shown.

View File

@@ -0,0 +1,87 @@
openapi: 3.0.0
info:
title: Connected Home API
description: This Swagger Doc provides usage information on the Connected Home public API.
version: 0.1.0
servers:
- url: http://localhost:8082/api
description: Local (development) server
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
paths:
/register:
post:
summary: Registers a new user and returns a JWT.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
password:
type: string
responses:
'201': # status code
description: A JSON Web Token
content:
application/json:
schema:
type: object
properties:
token:
type: string
/login:
post:
summary: Authenticates a user and returns a JWT.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
username:
type: string
password:
type: string
responses:
'200': # status code
description: A JSON Web Token
content:
application/json:
schema:
type: object
properties:
token:
type: string
/profile:
get:
summary: Returns a user profile
security:
- BearerAuth: []
responses:
'200': # status code
description: A JSON array of user names
content:
application/json:
schema:
type: object
properties:
first_name:
type: string
last_name:
type: string
street_number:
type: number
street:
type: string
city:
type: string
postal_code:
type: string

View File

@@ -31,7 +31,7 @@ pub async fn login(new_user: UserRequest) -> Response<Body> {
match response {
Ok(success_response) => {
let login_response = success_response.into_inner();
make_response(StatusCode::CREATED, Some(login_response.jwt))
make_response(StatusCode::OK, Some(login_response.jwt))
}
Err(err_response) => make_response(
StatusCode::BAD_REQUEST,

View File

@@ -0,0 +1,10 @@
[package]
name = "kafka-consumer"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rdkafka = "0.28.0"
tokio = { version = "1.17.0", features = ["full"] }

View File

@@ -0,0 +1,72 @@
use rdkafka::client::ClientContext;
use rdkafka::config::{ClientConfig, RDKafkaLogLevel};
use rdkafka::consumer::stream_consumer::StreamConsumer;
use rdkafka::consumer::{CommitMode, Consumer, ConsumerContext, Rebalance};
use rdkafka::error::KafkaResult;
use rdkafka::message::{Headers, Message};
use rdkafka::topic_partition_list::TopicPartitionList;
use rdkafka::util::get_rdkafka_version;
#[tokio::main]
async fn main() {
let context = CustomContext;
let consumer: LoggingConsumer = ClientConfig::new()
.set("group.id", "my-group")
.set("bootstrap.servers", "localhost:9092")
.set("enable.partition.eof", "false")
.set("session.timeout.ms", "6000")
.set("enable.auto.commit", "true")
.set_log_level(RDKafkaLogLevel::Debug)
.create_with_context(context)
.expect("Consumer creation failed");
consumer
.subscribe(vec!["my_topic"].as_slice())
.expect("Can't subscribe to specified topics");
loop {
match consumer.recv().await {
Err(e) => println!("Kafka error: {}", e),
Ok(m) => {
let payload = match m.payload_view::<str>() {
None => "",
Some(Ok(s)) => s,
Some(Err(e)) => {
println!("Error while deserializing message payload: {:?}", e);
""
}
};
println!("key: '{:?}', payload: '{}', topic: {}, partition: {}, offset: {}, timestamp: {:?}",
m.key(), payload, m.topic(), m.partition(), m.offset(), m.timestamp());
if let Some(headers) = m.headers() {
for i in 0..headers.count() {
let header = headers.get(i).unwrap();
println!(" Header {:#?}: {:?}", header.0, header.1);
}
}
consumer.commit_message(&m, CommitMode::Async).unwrap();
}
};
}
}
struct CustomContext;
impl ClientContext for CustomContext {}
impl ConsumerContext for CustomContext {
fn pre_rebalance(&self, rebalance: &Rebalance) {
println!("Pre rebalance {:?}", rebalance);
}
fn post_rebalance(&self, rebalance: &Rebalance) {
println!("Post rebalance {:?}", rebalance);
}
fn commit_callback(&self, result: KafkaResult<()>, _offsets: &TopicPartitionList) {
println!("Committing offsets: {:?}", result);
}
}
type LoggingConsumer = StreamConsumer<CustomContext>;

View File

@@ -0,0 +1,10 @@
[package]
name = "kafka-producer"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rdkafka = "0.28.0"
tokio = { version = "1.17.0", features = ["full"] }

View File

@@ -0,0 +1,27 @@
use rdkafka::config::ClientConfig;
use rdkafka::message::OwnedHeaders;
use rdkafka::producer::{FutureProducer, FutureRecord};
use std::time::Duration;
#[tokio::main]
async fn main() {
let producer: &FutureProducer = &ClientConfig::new()
.set("bootstrap.servers", "localhost:9092")
.set("message.timeout.ms", "5000")
.create()
.expect("Producer creation error");
let delivery_status = producer
.send(
FutureRecord::to("my_topic")
.payload(&format!("Hello, World"))
.key(&format!("KEY0"))
.headers(OwnedHeaders::new().add("header_key", "header_value")),
Duration::from_secs(2),
)
.await;
// This will be executed when the result is received.
println!("Delivery status for message received");
println!("{:?}", delivery_status);
}

View File

@@ -14,14 +14,12 @@ pub enum JwtError {
}
impl From<jwt::Error> for JwtError {
fn from(error: Error) -> Self {
match error {
_ => JwtError::INVALID,
}
fn from(_: Error) -> Self {
JwtError::INVALID
}
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Default, Debug, Deserialize, Serialize)]
pub struct Jwt {
pub token: String,
}
@@ -32,22 +30,15 @@ impl From<String> for Jwt {
}
}
impl Default for Jwt {
fn default() -> Self {
Self {
token: String::default(),
}
}
}
impl Display for Jwt {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
serde_json::to_string(self)
.map_err(|e| { warn!("Failed to serialize JWT with error: {}", e) })
.unwrap()
serde_json::to_string(self).map_err(|e| {
error!("Failed to serialize JWT with error: {}", e);
std::fmt::Error
})?
)
}
}
@@ -57,8 +48,14 @@ impl Jwt {
// todo: manage secrets
let key: Hmac<Sha256> = Hmac::new_from_slice(key.as_bytes()).unwrap();
let token: Token<Header, BTreeMap<String, String>, _> =
VerifyWithKey::verify_with_key(self.token.as_str(), &key)?;
let token: Token<Header, BTreeMap<String, String>, _> = VerifyWithKey::verify_with_key(
match self.token.find("Bearer ") {
Some(0) => &self.token[7..],
_ => &self.token,
},
&key,
)?;
let expiry = token.claims().get("expiry");
return match expiry {
Some(expiry) => {

View File

@@ -4,4 +4,3 @@ extern crate pretty_env_logger;
extern crate log;
pub mod jwt;
//pub mod user;

1
frontend/.env Normal file
View File

@@ -0,0 +1 @@
REACT_APP_BACKEND_URL = 'http://localhost:8082'

4
frontend/.gitignore vendored
View File

@@ -14,7 +14,7 @@
# misc
.DS_Store
.env.local
.env.development.local
.env
.env.test.local
.env.production.local
@@ -37,7 +37,7 @@ yarn-error.log*
# misc
.DS_Store
.env.local
.env.development.local
.env
.env.test.local
.env.production.local

12550
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@ import axios from "axios";
export function getCountries(token: string) {
const address = "http://localhost:8082/api/countries"
const address = `${process.env.REACT_APP_BACKEND_URL}/api/profile`;
return axios.create({
timeout: 45000,
@@ -12,7 +12,7 @@ export function getCountries(token: string) {
},
responseType: "json"
}).get(address, {headers: {
'Authorization': token
'Authorization': 'Bearer ' + token
}}).then(
({ data, status }) => {
if (status !== 200) {

View File

@@ -2,7 +2,7 @@ import axios from "axios";
export function login(token: string) {
const address = "http://localhost:8082/dashboard"
const address = `${process.env.REACT_APP_BACKEND_URL}/dashboard`;
return axios.create({
timeout: 45000,

View File

@@ -2,7 +2,7 @@ import axios from "axios";
export function login(username: string | undefined, password: string | undefined) {
const address = "http://localhost:8082/api/login"
const address = `${process.env.REACT_APP_BACKEND_URL}/api/login`;
let credentials = {
username,
password

12112
frontend/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
dependencies:
- name: kube-prometheus-stack
repository: https://prometheus-community.github.io/helm-charts
version: 13.13.1
digest: sha256:aba4816de5490484f7d0796a5d81c8ce772d9745a905edccbd15d5b532176647
generated: "2021-05-07T23:15:42.150318+02:00"

View File

@@ -0,0 +1,24 @@
apiVersion: v2
name: redpanda-operator
description: Redpanda operator helm chart
type: application
# This is the chart version. This is only placeholder that will be set during release process
version: 0.1.0
# This is the version number of the application being deployed. This is only placeholder that
# will be set during release process.
appVersion: v21.3.4
home: https://vectorized.io
sources:
- https://github.com/redpanda-data/redpanda
maintainers:
- name: Vectorizedio
email: support@vectorized.io
dependencies:
- name: kube-prometheus-stack
condition: monitoring.enabled
version: 13.13.1
repository: https://prometheus-community.github.io/helm-charts

View File

@@ -0,0 +1,88 @@
# Redpanda Operator
![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v21.3.4](https://img.shields.io/badge/AppVersion-v21.3.4-informational?style=flat-square)
## Installation
### Prerequisite
To deploy operator with webhooks (enabled by default) please install
cert manager. Please follow
[the installation guide](https://cert-manager.io/docs/installation/)
The cert manager needs around 1 minute to be ready. The helm chart
will create Issuer and Certificate custom resource. The
webhook of cert-manager will prevent from creating mentioned
resources. To verify that cert manager is ready please follow
[the verifying the installation](https://cert-manager.io/docs/installation/kubernetes/#verifying-the-installation)
The operator by default exposes metrics endpoint. By leveraging prometheus
operator ServiceMonitor custom resource metrics can be automatically
discovered.
1. Install Redpanda operator CRDs:
```sh
kubectl apply -k 'https://github.com/redpanda-data/redpanda/src/go/k8s/config/crd?ref=v21.3.4'
```
> The CRDs are decoupled from helm chart, so that helm release can be
> removed without cascading deletion of underling custom resources.
> Other argument for decoupling is that helm cli can incorrectly
> patch the Custom Resource Definition.
### Helm installation
1. Install the Redpanda operator:
> The example command should be invoked from `src/go/k8s/helm-chart/charts`
```sh
helm install --namespace redpanda-system --create-namespace redpanda-system ./redpanda-operator
```
Alternative installation with kube-prometheus-stack that includes prometheus operator CRD
```sh
helm install --dependency-update \
--namespace redpanda-system \
--set monitoring.enabled=true \
--create-namespace redpanda-operator ./redpanda-operator
```
Other instruction will be visible after installation.
## Values
| Key | Type | Default | Description |
|-----|------|---------|-------------|
| affinity | object | `{}` | Allows to specify affinity for Redpanda Operator PODs |
| config.apiVersion | string | `"controller-runtime.sigs.k8s.io/v1alpha1"` | |
| config.health.healthProbeBindAddress | string | `":8081"` | |
| config.kind | string | `"ControllerManagerConfig"` | |
| config.leaderElection.leaderElect | bool | `true` | |
| config.leaderElection.resourceName | string | `"aa9fc693.vectorized.io"` | |
| config.metrics.bindAddress | string | `"127.0.0.1:8080"` | |
| config.webhook.port | int | `9443` | |
| configurator.pullPolicy | string | `"IfNotPresent"` | Define the pullPolicy for Redpanda configurator image |
| configurator.repository | string | `"vectorized/configurator"` | Repository that Redpanda configurator image is available |
| configurator.tag | string | `"{{ .Chart.AppVersion }}"` | Define the Redpanda configurator container tag |
| clusterDomain | string | `cluster.local` | Defines Kubernetes Cluster Domain |
| fullnameOverride | string | `""` | Override the fully qualified app name |
| image.pullPolicy | string | `"IfNotPresent"` | Define the pullPolicy for Redpanda Operator image |
| image.repository | string | `"vectorized/redpanda-operator"` | Repository that Redpanda Operator image is available |
| image.tag | string | `"{{ .Chart.AppVersion }}"` | Define the Redpanda Operator container tag |
| imagePullSecrets | list | `[]` | Redpanda Operator container registry pullSecret (ex: specify docker registry credentials) |
| labels | string | `nil` | Allows to assign labels to the resources created by this helm chart |
| logLevel | string | `"info"` | Set Redpanda Operator log level (debug, info, error, panic, fatal) |
| monitoring | object | `{"enabled":false}` | Add service monitor to the deployment |
| nameOverride | string | `""` | Override name of app |
| nodeSelector | object | `{}` | Allows to schedule Redpanda Operator on specific nodes |
| podAnnotations | object | `{}` | Allows setting additional annotations for Redpanda Operator PODs |
| podLabels | object | `{}` | Allows setting additional labels for for Redpanda Operator PODs |
| rbac.create | bool | `true` | Specifies whether the RBAC resources should be created |
| replicaCount | int | `1` | Number of instances of Redpanda Operator |
| resources | object | `{}` | Set resources requests/limits for Redpanda Operator PODs |
| serviceAccount.create | bool | `true` | Specifies whether a service account should be created |
| serviceAccount.name | string | `nil` | The name of the service account to use. If not set name is generated using the fullname template |
| tolerations | list | `[]` | Allows to schedule Redpanda Operator on tainted nodes |
| webhook.enabled | bool | `true` | |

View File

@@ -0,0 +1,54 @@
# Redpanda Operator
{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }}
## Installation
### Prerequisite
To deploy operator with webhooks (enabled by default) please install
cert manager. Please follow
[the installation guide](https://cert-manager.io/docs/installation/)
The cert manager needs around 1 minute to be ready. The helm chart
will create Issuer and Certificate custom resource. The
webhook of cert-manager will prevent from creating mentioned
resources. To verify that cert manager is ready please follow
[the verifying the installation](https://cert-manager.io/docs/installation/kubernetes/#verifying-the-installation)
The operator by default exposes metrics endpoint. By leveraging prometheus
operator ServiceMonitor custom resource metrics can be automatically
discovered.
1. Install Redpanda operator CRDs:
```sh
kubectl apply -k 'https://github.com/redpanda-data/redpanda/src/go/k8s/config/crd?ref={{ template "chart.appVersion" . }}'
```
> The CRDs are decoupled from helm chart, so that helm release can be
> removed without cascading deletion of underling custom resources.
> Other argument for decoupling is that helm cli can incorrectly
> patch the Custom Resource Definition.
### Helm installation
1. Install the Redpanda operator:
> The example command should be invoked from `src/go/k8s/helm-chart/charts`
```sh
helm install --namespace redpanda-system --create-namespace redpanda-operator ./redpanda-operator
```
Alternative installation with kube-prometheus-stack that includes prometheus operator CRD
```sh
helm install --dependency-update \
--namespace redpanda-system \
--set monitoring.enabled=true \
--create-namespace redpanda-operator ./redpanda-operator
```
Other instruction will be visible after installation.
{{ template "chart.valuesSection" . }}

View File

@@ -0,0 +1,20 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
Congratulations on installing {{ .Chart.Name }}!
The pods will rollout in a few seconds. To check the status:
kubectl -n {{ .Release.Namespace }} rollout status -w deployment/{{ template "redpanda-operator.fullname" . }}
Now you can install Cluster custom resource:
kubectl apply -f https://raw.githubusercontent.com/redpanda-data/redpanda/dev/src/go/k8s/config/samples/one_node_cluster.yaml

View File

@@ -0,0 +1,66 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{/*
Expand the name of the chart.
*/}}
{{- define "redpanda-operator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "redpanda-operator.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "redpanda-operator.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "redpanda-operator.webhook-cert" -}}
{{- printf .Values.webhookSecretName }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "redpanda-operator.labels" -}}
app.kubernetes.io/name: {{ include "redpanda-operator.name" . }}
helm.sh/chart: {{ include "redpanda-operator.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
{{/*
Create the name of the service account to use
*/}}
{{- define "redpanda-operator.serviceAccountName" -}}
{{ default (include "redpanda-operator.fullname" .) .Values.serviceAccount.name }}
{{- end -}}

View File

@@ -0,0 +1,27 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.webhook.enabled }}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: redpanda-serving-cert
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
spec:
dnsNames:
- {{ include "redpanda-operator.name" . }}-webhook-service.{{ .Release.Namespace }}.svc
- {{ include "redpanda-operator.name" . }}-webhook-service.{{ .Release.Namespace }}.svc.{{ .Values.clusterDomain }}
issuerRef:
kind: Issuer
name: {{ include "redpanda-operator.fullname" . }}-selfsigned-issuer
secretName: {{ include "redpanda-operator.webhook-cert" . }}
{{- end }}

View File

@@ -0,0 +1,166 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "redpanda-operator.fullname" . }}
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
rules:
- apiGroups:
- apps
resources:
- statefulsets
verbs:
- create
- get
- list
- patch
- update
- watch
- delete
- apiGroups:
- cert-manager.io
resources:
- certificates
- clusterissuers
- issuers
verbs:
- create
- delete
- get
- list
- patch
- watch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
- delete
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- get
- list
- watch
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- services
verbs:
- create
- get
- list
- patch
- update
- watch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterrolebindings
- clusterroles
verbs:
- create
- get
- list
- patch
- update
- watch
- apiGroups:
- redpanda.vectorized.io
resources:
- clusters
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- redpanda.vectorized.io
resources:
- clusters/finalizers
verbs:
- update
- apiGroups:
- redpanda.vectorized.io
resources:
- clusters/status
verbs:
- get
- patch
- update
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
{{- end -}}

View File

@@ -0,0 +1,27 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "redpanda-operator.fullname" . }}
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "redpanda-operator.fullname" . }}
subjects:
- kind: ServiceAccount
name: {{ template "redpanda-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end -}}

View File

@@ -0,0 +1,24 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "redpanda-operator.fullname" . }}-metrics-reader
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
rules:
- nonResourceURLs:
- /metrics
verbs:
- get
{{- end -}}

View File

@@ -0,0 +1,32 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "redpanda-operator.fullname" . }}-proxy-role
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
rules:
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
{{- end -}}

View File

@@ -0,0 +1,27 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "redpanda-operator.fullname" . }}-proxy-role
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "redpanda-operator.fullname" . }}-proxy-role
subjects:
- kind: ServiceAccount
name: {{ template "redpanda-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end -}}

View File

@@ -0,0 +1,20 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "redpanda-operator.fullname" . }}-config
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
data:
controller_manager_config.yaml: |
{{ .Values.config }}

View File

@@ -0,0 +1,118 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "redpanda-operator.fullname" . }}
labels:
{{ include "redpanda-operator.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "redpanda-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "redpanda-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- if .Values.podLabels }}
{{ toYaml .Values.podLabels | nindent 8 }}
{{- end }}
annotations:
{{- if .Values.podAnnotations }}
{{ toYaml .Values.podAnnotations | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "redpanda-operator.serviceAccountName" . }}
containers:
- args:
- --secure-listen-address=0.0.0.0:8443
- --upstream=http://127.0.0.1:8080/
- --logtostderr=true
- --v=10
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0
name: kube-rbac-proxy
ports:
- containerPort: 8443
name: https
- name: manager
image: "{{ .Values.image.repository }}:{{ tpl .Values.image.tag . }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
args:
- --health-probe-bind-address=:8081
- --metrics-bind-address=127.0.0.1:8080
- --leader-elect
- --configurator-tag={{ tpl .Values.configurator.tag . }}
- --configurator-base-image={{ .Values.configurator.repository }}
- --configurator-image-pull-policy={{ .Values.configurator.pullPolicy }}
- --cluster-domain={{ .Values.clusterDomain }}
{{- if .Values.webhook.enabled }}
- --webhook-enabled=true
{{- else }}
- --webhook-enabled=false
{{- end }}
command:
- /manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
livenessProbe:
httpGet:
path: /healthz/
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
securityContext:
allowPrivilegeEscalation: false
{{- if .Values.webhook.enabled }}
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
securityContext:
runAsUser: 65532
terminationGracePeriodSeconds: 10
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.webhook.enabled }}
volumes:
- name: cert
secret:
defaultMode: 420
secretName: {{ include "redpanda-operator.webhook-cert" . }}
{{- end }}

View File

@@ -0,0 +1,21 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.webhook.enabled }}
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: {{ include "redpanda-operator.fullname" . }}-selfsigned-issuer
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
spec:
selfSigned: {}
{{- end }}

View File

@@ -0,0 +1,41 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.webhook.enabled }}
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/redpanda-serving-cert
name: {{ include "redpanda-operator.fullname" . }}-mutating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: {{ include "redpanda-operator.name" . }}-webhook-service
namespace: {{ .Release.Namespace }}
path: /mutate-redpanda-vectorized-io-v1alpha1-cluster
failurePolicy: Fail
name: mcluster.kb.io
rules:
- apiGroups:
- redpanda.vectorized.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- clusters
sideEffects: None
{{- end }}

View File

@@ -0,0 +1,41 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.rbac.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "redpanda-operator.fullname" . }}-election-role
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
rules:
- apiGroups:
- ""
- coordination.k8s.io
resources:
- configmaps
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
{{- end}}

View File

@@ -0,0 +1,27 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.rbac.create -}}
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: {{ include "redpanda-operator.fullname" . }}-election-rolebinding
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
subjects:
- kind: ServiceAccount
name: {{ include "redpanda-operator.fullname" . }}
namespace: {{ .Release.Namespace }}
roleRef:
kind: Role
name: {{ include "redpanda-operator.fullname" . }}-election-role
apiGroup: rbac.authorization.k8s.io
{{- end -}}

View File

@@ -0,0 +1,19 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ template "redpanda-operator.serviceAccountName" . }}
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
{{- end -}}

View File

@@ -0,0 +1,25 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "redpanda-operator.name" . }}-metrics-service
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
spec:
ports:
- name: https
port: 8443
targetPort: https
selector:
app.kubernetes.io/name: {{ include "redpanda-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}

View File

@@ -0,0 +1,26 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.webhook.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "redpanda-operator.name" . }}-webhook-service
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
spec:
ports:
- port: 443
targetPort: 9443
selector:
app.kubernetes.io/name: {{ include "redpanda-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}

View File

@@ -0,0 +1,33 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.monitoring.enabled -}}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "redpanda-operator.name" . }}-metrics-monitor
labels:
{{ include "redpanda-operator.labels" . | indent 4 }}
spec:
endpoints:
- bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
path: /metrics
port: https
scheme: https
tlsConfig:
insecureSkipVerify: true
namespaceSelector:
matchNames:
- {{ .Release.Namespace }}
selector:
matchLabels:
{{ include "redpanda-operator.labels" . | indent 6 }}
{{- end -}}

View File

@@ -0,0 +1,57 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: rpk-config
annotations:
"helm.sh/hook": test
"helm.sh/hook-weight": "1"
data:
redpanda.yaml: |
redpanda:
rpk:
tls:
key_file: /etc/tls/certs/tls.key
cert_file: /etc/tls/certs/tls.crt
truststore_file: /etc/tls/certs/ca.crt
---
apiVersion: batch/v1
kind: Job
metadata:
name: create-test-topic-tls
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": hook-succeeded
"helm.sh/hook-weight": "2"
spec:
template:
spec:
volumes:
- name: tlscert
secret:
defaultMode: 420
secretName: cluster-tls-user-client
- name: rpkconfig
configMap:
name: rpk-config
containers:
- name: rpk
image: vectorized/redpanda:latest
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
command:
- /bin/bash
- -c
args:
- rpk topic create test --brokers cluster-tls-0.cluster-tls.$POD_NAMESPACE.svc.cluster.local:9092 -v
volumeMounts:
- mountPath: /etc/tls/certs
name: tlscert
- mountPath: /etc/redpanda
name: rpkconfig
restartPolicy: Never
backoffLimit: 6
parallelism: 1
completions: 1

View File

@@ -0,0 +1,30 @@
apiVersion: redpanda.vectorized.io/v1alpha1
kind: Cluster
metadata:
name: cluster-tls
annotations:
"helm.sh/hook": test
spec:
image: "vectorized/redpanda"
version: "latest"
replicas: 3
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 1
memory: 1.2Gi
configuration:
rpcServer:
port: 33145
kafkaApi:
- port: 9092
tls:
enabled: true
requireClientAuth: true
adminApi:
- port: 9644
pandaproxyApi:
- port: 8082
developerMode: true

View File

@@ -0,0 +1,41 @@
{{/*
Copyright 2020 Redpanda Data, Inc.
Use of this software is governed by the Business Source License
included in the file licenses/BSL.md
As of the Change Date specified in that file, in accordance with
the Business Source License, use of this software will be governed
by the Apache License, Version 2.0
*/}}
{{- if .Values.webhook.enabled -}}
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/redpanda-serving-cert
name: {{ include "redpanda-operator.fullname" . }}-validating-webhook-configuration
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: {{ include "redpanda-operator.name" . }}-webhook-service
namespace: {{ .Release.Namespace }}
path: /validate-redpanda-vectorized-io-v1alpha1-cluster
failurePolicy: Fail
name: mcluster.kb.io
rules:
- apiGroups:
- redpanda.vectorized.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- clusters
sideEffects: None
{{- end -}}

View File

@@ -0,0 +1,100 @@
# Default values for redpanda-operator.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
# nameOverride -- Override name of app
nameOverride: ""
# fullnameOverride -- Override the fully qualified app name
fullnameOverride: ""
# replicaCount -- Number of instances of Redpanda Operator
replicaCount: 1
# Kubernetes Cluster Domain
clusterDomain: cluster.local
image:
# image.repository -- Repository that Redpanda Operator image is available
repository: vectorized/redpanda-operator
# image.tag -- Define the Redpanda Operator container tag
tag: |-
{{ .Chart.AppVersion }}
# image.pullPolicy -- Define the pullPolicy for Redpanda Operator image
pullPolicy: IfNotPresent
configurator:
# configurator.repository -- Repository that Redpanda configurator image is available
repository: vectorized/configurator
# configurator.tag -- Define the Redpanda configurator container tag
tag: |-
{{ .Chart.AppVersion }}
# configurator.pullPolicy -- Define the pullPolicy for Redpanda configurator image
pullPolicy: IfNotPresent
config:
apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
kind: ControllerManagerConfig
health:
healthProbeBindAddress: :8081
metrics:
bindAddress: 127.0.0.1:8080
webhook:
port: 9443
leaderElection:
leaderElect: true
resourceName: aa9fc693.vectorized.io
# imagePullSecrets -- Redpanda Operator container registry pullSecret (ex: specify docker registry credentials)
imagePullSecrets: []
# logLevel -- Set Redpanda Operator log level (debug, info, error, panic, fatal)
logLevel: "info"
rbac:
# rbac.create -- Specifies whether the RBAC resources should be created
create: true
webhook:
# webhook.create -- Specifies whether the Webhook resources should configured
enabled: true
serviceAccount:
# serviceAccount.create -- Specifies whether a service account should be created
create: true
# serviceAccount.name -- The name of the service account to use. If not set name is generated using the fullname template
name:
# resources -- Set resources requests/limits for Redpanda Operator PODs
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 30Mi
# requests:
# cpu: 100m
# memory: 20Mi
# nodeSelector -- Allows to schedule Redpanda Operator on specific nodes
nodeSelector: {}
# tolerations -- Allows to schedule Redpanda Operator on tainted nodes
tolerations: []
# affinity -- Allows to specify affinity for Redpanda Operator PODs
affinity: {}
# podAnnotations -- Allows setting additional annotations for Redpanda Operator PODs
podAnnotations: {}
# podLabels -- Allows setting additional labels for for Redpanda Operator PODs
podLabels: {}
# labels -- Allows to assign labels to the resources created by this helm chart
labels:
# monitoring -- Add service monitor to the deployment
monitoring:
enabled: false
webhookSecretName: webhook-server-cert

26
helm/redpanda/Chart.yaml Normal file
View File

@@ -0,0 +1,26 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
apiVersion: v2
name: redpanda
description: Redpanda is the real-time engine for modern apps.
type: application
version: 1.0.4
appVersion: latest
sources:
- https://github.com/vectorizedio/helm-charts
maintainers:
- name: rkruze
email: roko@vectorized.io

View File

@@ -0,0 +1,34 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
Congratulations on installing {{ .Chart.Name }}!
The pods will rollout in a few seconds. To check the status:
kubectl -n {{ .Release.Namespace }} rollout status -w statefulset/{{ template "redpanda.fullname" . }}
Try some sample commands, like creating a topic called topic1:
kubectl -n {{ .Release.Namespace }} run -ti --rm --restart=Never \
--image {{ .Values.image.repository }}:{{ .Values.image.tag }} \
rpk -- --brokers={{ include "redpanda.fullname" . }}-bootstrap:{{ template "redpanda.kafka.internal.advertise.port" $ }} topic create topic1
To get the api status:
kubectl -n {{ .Release.Namespace }} run -ti --rm --restart=Never \
--image {{ .Values.image.repository }}:{{ .Values.image.tag }} \
rpk -- --brokers={{ include "redpanda.fullname" . }}-bootstrap:{{ template "redpanda.kafka.internal.advertise.port" $ }} cluster info

View File

@@ -0,0 +1,115 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{/*
Expand the name of the chart.
*/}}
{{- define "redpanda.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "redpanda.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s" .Release.Name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "redpanda.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "redpanda.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "redpanda.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
{{/*
Strip out the suffixes on memory to pass to Redpanda
*/}}
{{- define "redpanda.parseMemory" -}}
{{- $type := typeOf .Values.statefulset.resources.limits.memory }}
{{- if eq $type "float64" }}
{{- .Values.statefulset.resources.limits.memory | int64 }}
{{- else if eq $type "int" }}
{{- .Values.statefulset.resources.limits.memory }}
{{- else }}
{{- $string := .Values.statefulset.resources.limits.memory | toString }}
{{- regexReplaceAll "(\\d+)(\\w?)i?" $string "${1}${2}" }}
{{- end }}
{{- end }}
{{/*
Generate configuration needed for rpk
*/}}
{{- define "redpanda.internal.domain" -}}
{{- $service := include "redpanda.fullname" . -}}
{{- $ns := .Release.Namespace -}}
{{- $domain := .Values.clusterDomain | trimSuffix "." -}}
{{- printf "%s.%s.svc.%s." $service $ns $domain -}}
{{- end }}
{{- define "redpanda.kafka.internal.advertise.address" -}}
{{- $host := "$(SERVICE_NAME)" -}}
{{- $domain := include "redpanda.internal.domain" . -}}
{{- printf "%s.%s" $host $domain -}}
{{- end -}}
{{- define "redpanda.kafka.internal.advertise.port" -}}
{{- (first .Values.config.redpanda.kafka_api).port -}}
{{- end -}}
{{- define "redpanda.kafka.internal.listen.address" -}}
{{- "$(POD_IP)" -}}
{{- end -}}
{{- define "redpanda.kafka.internal.listen.port" -}}
{{- (first .Values.config.redpanda.kafka_api).port -}}
{{- end -}}
{{- define "redpanda.rpc.advertise.address" -}}
{{- $host := "$(SERVICE_NAME)" -}}
{{- $domain := include "redpanda.internal.domain" . -}}
{{- printf "%s.%s" $host $domain -}}
{{- end -}}
{{- define "redpanda.rpc.advertise.port" -}}
{{- .Values.config.redpanda.rpc_server.port -}}
{{- end -}}
{{- define "redpanda.rpc.listen.address" -}}
{{- "$(POD_IP)" -}}
{{- end -}}
{{- define "redpanda.rpc.listen.port" -}}
{{- .Values.config.redpanda.rpc_server.port -}}
{{- end -}}

View File

@@ -0,0 +1,46 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "redpanda.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
helm.sh/chart: {{ template "redpanda.chart" . }}
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
data:
redpanda.yaml: |
config_file: /etc/redpanda/redpanda.yaml
license_key: {{ .Values.config.license_key }}
organization: {{ .Values.config.organization }}
redpanda:
{{ toYaml .Values.config.redpanda | indent 6 }}
seed_servers:
{{- range untilStep 0 (.Values.statefulset.replicas|int) 1 }}
- host:
address: "{{ template "redpanda.fullname" $ }}-{{ . }}.{{ template "redpanda.internal.domain" $ }}"
port: {{ template "redpanda.rpc.advertise.port" $ }}
{{- end }}
rpk:
{{ toYaml .Values.config.rpk | indent 6 }}

View File

@@ -0,0 +1,37 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: {{ template "redpanda.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
helm.sh/chart: {{ template "redpanda.chart" . }}
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
maxUnavailable: {{ .Values.statefulset.budget.maxUnavailable | int64 }}

View File

@@ -0,0 +1,44 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
# This is the service that should be used by other clients
# in the Kubernetes cluster. This will only work within the
# cluster and should not be publicly exposed via a load balancer.
apiVersion: v1
kind: Service
metadata:
name: {{ include "redpanda.fullname" . }}-bootstrap
namespace: {{ .Release.Namespace | quote }}
labels:
helm.sh/chart: {{ template "redpanda.chart" . }}
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
type: ClusterIP
ports:
- name: kafka-tcp
protocol: TCP
port: {{ template "redpanda.kafka.internal.advertise.port" $ }}
targetPort: {{ template "redpanda.kafka.internal.advertise.port" $ }}
selector:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}

View File

@@ -0,0 +1,45 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
# This service is only used to create the DNS enteries for each pod in
# the stateful set. This service should not be used by any client
# application
apiVersion: v1
kind: Service
metadata:
name: {{ include "redpanda.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
helm.sh/chart: {{ template "redpanda.chart" . }}
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
clusterIP: None
publishNotReadyAddresses: true
ports:
- name: kafka-tcp
protocol: TCP
port: {{ template "redpanda.kafka.internal.advertise.port" $ }}
targetPort: {{ template "redpanda.kafka.internal.advertise.port" $ }}
selector:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}

View File

@@ -0,0 +1,37 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "redpanda.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
helm.sh/chart: {{ template "redpanda.chart" . }}
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,222 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ template "redpanda.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
helm.sh/chart: {{ template "redpanda.chart" . }}
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
selector:
matchLabels:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
serviceName: {{ template "redpanda.fullname" . }}
replicas: {{ .Values.statefulset.replicas | int64 }}
updateStrategy: {{- toYaml .Values.statefulset.updateStrategy | nindent 4 }}
podManagementPolicy: {{ .Values.statefulset.podManagementPolicy | quote }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.statefulset.annotations }}
annotations: {{- toYaml . | nindent 8 }}
{{- end }}
spec:
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
# TODO:
# * Figure out what to do about node_id / seeds here - the operator will fix this separately
# * Once that's done, this initContainer can be removed
initContainers:
- name: {{ template "redpanda.name" . }}-configurator
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
command: ["/bin/sh", "-c"]
env:
- name: SERVICE_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
args:
- >
CONFIG=/etc/redpanda/redpanda.yaml;
NODE_ID=${SERVICE_NAME##*-};
cp /tmp/base-config/redpanda.yaml "$CONFIG";
rpk --config "$CONFIG" config set redpanda.node_id $NODE_ID;
if [ "$NODE_ID" = "0" ]; then
rpk --config "$CONFIG" config set redpanda.seed_servers '[]' --format yaml;
fi;
volumeMounts:
- name: {{ template "redpanda.fullname" . }}
mountPath: /tmp/base-config
- name: config
mountPath: /etc/redpanda
resources:
{{- toYaml .Values.statefulset.resources | nindent 12 }}
containers:
- name: {{ template "redpanda.name" . }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
env:
- name: SERVICE_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
args:
- >
redpanda
start
--smp={{ .Values.statefulset.resources.limits.cpu }}
--memory={{ template "redpanda.parseMemory" . }}
--reserve-memory=0M
--advertise-kafka-addr=internal://{{ template "redpanda.kafka.internal.advertise.address" . }}:{{ template "redpanda.kafka.internal.advertise.port" . }}
--kafka-addr=internal://{{ template "redpanda.kafka.internal.listen.address" . }}:{{ template "redpanda.kafka.internal.listen.port" . }}
--advertise-rpc-addr={{ template "redpanda.rpc.advertise.address" . }}:{{ template "redpanda.rpc.advertise.port" . }}
--rpc-addr={{ template "redpanda.rpc.listen.address" . }}:{{ template "redpanda.rpc.listen.port" . }}
--
--default-log-level={{ .Values.config.seastar.default_log_level }}
ports:
- containerPort: {{ .Values.config.redpanda.admin.port }}
name: admin
- containerPort: {{ template "redpanda.kafka.internal.listen.port" . }}
name: kafka
- containerPort: {{ template "redpanda.rpc.listen.port" $ }}
name: rpc
volumeMounts:
- name: datadir
mountPath: /var/lib/redpanda/data
- name: config
mountPath: /etc/redpanda
resources:
{{- toYaml .Values.statefulset.resources | nindent 12 }}
volumes:
- name: datadir
{{- if .Values.storage.persistentVolume.enabled }}
persistentVolumeClaim:
claimName: datadir
{{- else if .Values.storage.hostPath }}
hostPath:
path: {{ .Values.storage.hostPath | quote }}
{{- else }}
emptyDir: {}
{{- end }}
- name: {{ template "redpanda.fullname" . }}
configMap:
name: {{ template "redpanda.fullname" . }}
- name: config
emptyDir: {}
{{- if or .Values.statefulset.nodeAffinity .Values.statefulset.podAffinity .Values.statefulset.podAntiAffinity }}
affinity:
{{- with .Values.statefulset.nodeAffinity }}
nodeAffinity: {{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.statefulset.podAffinity }}
podAffinity: {{- toYaml . | nindent 10 }}
{{- end }}
{{- if .Values.statefulset.podAntiAffinity }}
podAntiAffinity:
{{- if .Values.statefulset.podAntiAffinity.type }}
{{- if eq .Values.statefulset.podAntiAffinity.type "hard" }}
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: {{ .Values.statefulset.podAntiAffinity.topologyKey }}
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
{{- else if eq .Values.statefulset.podAntiAffinity.type "soft" }}
preferredDuringSchedulingIgnoredDuringExecution:
- weight: {{ .Values.statefulset.podAntiAffinity.weight | int64 }}
podAffinityTerm:
topologyKey: {{ .Values.statefulset.podAntiAffinity.topologyKey }}
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
{{- end }}
{{- else }}
{{- toYaml .Values.statefulset.podAntiAffinity | nindent 10 }}
{{- end }}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.16-0" .Capabilities.KubeVersion.GitVersion }}
topologySpreadConstraints:
- labelSelector:
matchLabels:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
{{- with .Values.statefulset.topologySpreadConstraints }}
maxSkew: {{ .maxSkew }}
topologyKey: {{ .topologyKey }}
whenUnsatisfiable: {{ .whenUnsatisfiable }}
{{- end }}
{{- end }}
{{- with .Values.statefulset.nodeSelector }}
nodeSelector: {{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.statefulset.priorityClassName }}
priorityClassName: {{ .Values.statefulset.priorityClassName }}
{{- end }}
{{- with .Values.statefulset.tolerations }}
tolerations: {{- toYaml . | nindent 8 }}
{{- end }}
{{- if .Values.storage.persistentVolume.enabled }}
volumeClaimTemplates:
- metadata:
name: datadir
labels:
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.storage.persistentVolume.labels }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.labels }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.storage.persistentVolume.annotations }}
annotations: {{- toYaml . | nindent 10 }}
{{- end }}
spec:
accessModes: ["ReadWriteOnce"]
{{- if .Values.storage.persistentVolume.storageClass }}
{{- if (eq "-" .Values.storage.persistentVolume.storageClass) }}
storageClassName: ""
{{- else }}
storageClassName: {{ .Values.storage.persistentVolume.storageClass | quote}}
{{- end }}
{{- end }}
resources:
requests:
storage: {{ .Values.storage.persistentVolume.size | quote }}
{{- end }}

View File

@@ -0,0 +1,49 @@
{{/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/}}
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "redpanda.fullname" . }}-test-api-status"
namespace: {{ .Release.Namespace | quote }}
labels:
helm.sh/chart: {{ template "redpanda.chart" . }}
app.kubernetes.io/name: {{ template "redpanda.name" . }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/component: {{ template "redpanda.name" . }}
{{- with .Values.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
annotations:
"helm.sh/hook": test
"helm.sh/hook-delete-policy": hook-succeeded
spec:
restartPolicy: Never
containers:
- name: {{ template "redpanda.name" . }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
args: ["api", "status", "--brokers", "{{ include "redpanda.fullname" . }}:{{ template "redpanda.kafka.internal.advertise.port" $ }}"]
volumeMounts:
- name: {{ template "redpanda.fullname" . }}
mountPath: /tmp/base-config
volumes:
- name: {{ template "redpanda.fullname" . }}
configMap:
name: {{ template "redpanda.fullname" . }}
- name: config
emptyDir: {}

217
helm/redpanda/values.yaml Normal file
View File

@@ -0,0 +1,217 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# values.yaml
#
# This file contains values for variables referenced from yaml files in the templates directory.
#
# For further information on Helm templating see the documentation at:
# https://helm.sh/docs/chart_template_guide/values_files/
#
# For an explanation of Redpanda configuration values:
# https://vectorized.io/docs/advanced-configuration/
image:
repository: vectorized/redpanda
# The imagePullPolicy will default to Always when the tag is 'latest'
tag: v21.3.3
# Additional labels to apply to all Kubernetes resources created by this chart.
labels: {}
# app.kubernetes.io/part-of: my-app
clusterDomain: cluster.local
# See https://vectorized.io/docs/configuration/
config:
# If you have a license key please set it here or you can request one
# here: https://vectorized.io/redpanda
license_key: ""
# Update with your organization name
organization: ""
redpanda:
admin:
# The port for the admin server.
#
# Metrics are served off of this port at /metrics.
port: 9644
# Kafka API listeners
# The first entry is used to set up the headless service.
# Other entries are ignored.
kafka_api:
- name: internal
address: $(POD_IP)
port: 9092
# rpc server listener
rpc_server:
port: 33145
rpk:
# Enables memory locking.
enable_memory_locking: false
# Send usage stats back to vectorized
enable_usage_stats: true
# This should be set to true unless with have CPU affinity
# https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/#static-policy
#
# Equivalent to passing the following to redpanda
# --idle-poll-time-us 0 --thread-affinity 0 --poll-aio 0
overprovisioned: true
# Increases the number of allowed asynchronous IO events
tune_aio_events: false
# Syncs NTP
tune_clocksource: false
# Installs a custom script to process coredumps and save them to the given directory.
tune_coredump: false
# Disables hyper-threading, sets the ACPI-cpufreq governor to 'performance'. Additionaly
# if system reboot is allowed: disables Intel P-States, disables Intel C-States,
# disables Turbo Boost
#
# This is not possible to set to true while running in a container.
tune_cpu: false
# Distributes IRQs across cores with the method deemed the most appropriate for the
# current device type (i.e. NVMe)
#
# This is not possible to set to true while running in a container.
tune_disk_irq: false
seastar:
default_log_level: info
statefulset:
replicas: 1
updateStrategy:
type: RollingUpdate
podManagementPolicy: Parallel
budget:
maxUnavailable: 1
# Additional annotations to apply to the Pods of this StatefulSet.
annotations: {}
# Redpanda makes use of a thread per core model which is described here:
# https://vectorized.io/blog/tpc-buffers/ For this reason Redpanda should
# only be given full cores for requests and limits. The recommendation
# for memory for Redpanda is at least 2GB per core. These values will also
# affect the --smp and --memory flags which are passed to Redpanda.
#
# Limits are only specified as to provide Guaranteed QoS:
# https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#create-a-pod-that-gets-assigned-a-qos-class-of-guaranteed
#
# To improve performance further it is recommended to enable CPU Affinity:
# https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/#static-policy
#
# NOTE: You can increase the number of cores but decreasing the number
# is not supported currently.
# https://github.com/vectorizedio/redpanda/issues/350#
resources:
limits:
cpu: 1
memory: 2Gi
# Inter-Pod Affinity rules for scheduling Pods of this StatefulSet.
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity
podAffinity: {}
# Anti-affinity rules for scheduling Pods of this StatefulSet.
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#inter-pod-affinity-and-anti-affinity
# You may either toggle options below for default anti-affinity rules,
# or specify the whole set of anti-affinity rules instead of them.
podAntiAffinity:
# The topologyKey to be used.
# Can be used to spread across different nodes, AZs, regions etc.
topologyKey: kubernetes.io/hostname
# Type of anti-affinity rules: either `soft`, `hard` or empty value (which
# disables anti-affinity rules).
type: soft
# Weight for `soft` anti-affinity rules.
# Does not apply for other anti-affinity types.
weight: 100
# Node selection constraints for scheduling Pods of this StatefulSet.
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: {}
# PriorityClassName given to Pods of this StatefulSet
# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
priorityClassName: ""
# Taints to be tolerated by Pods of this StatefulSet.
# https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
tolerations: []
# https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
topologySpreadConstraints:
maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
serviceAccount:
# Specifies whether a service account should be created
create: false
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
# When using persistent storage the volume will be mounted as root. In order for redpanda to use the volume
# we must set the fsGroup to the uid of redpanda, which is 101
podSecurityContext:
fsGroup: 101
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
storage:
# Absolute path on host to store Redpanda's data.
# If not specified, then `emptyDir` will be used instead.
# If specified, but `persistentVolume.enabled` is `true`, then has no effect.
hostPath: ""
# If `enabled` is `true` then a PersistentVolumeClaim will be created and
# used to store Redpanda's data, otherwise `hostPath` is used.
persistentVolume:
enabled: true
size: 100Gi
# If defined, then `storageClassName: <storageClass>`.
# If set to "-", then `storageClassName: ""`, which disables dynamic
# provisioning.
# If undefined or empty (default), then no `storageClassName` spec is set,
# so the default provisioner will be chosen (gp2 on AWS, standard on
# GKE, AWS & OpenStack).
storageClass: ""
# Additional labels to apply to the created PersistentVolumeClaims.
labels: {}
# Additional annotations to apply to the created PersistentVolumeClaims.
annotations: {}

23
helm/swagger/.helmignore Normal file
View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

7
helm/swagger/Chart.yaml Normal file
View File

@@ -0,0 +1,7 @@
apiVersion: v2
name: swagger
description: Our Swagger Documentation
type: application
version: 0.1.0
appVersion: "0.1.0"

View File

@@ -0,0 +1 @@
../../../crates/api-gateway/doc/swagger.yaml

View File

@@ -0,0 +1,22 @@
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "api-gateway.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "api-gateway.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "api-gateway.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "api-gateway.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
{{- end }}

View File

@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "api-gateway.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "api-gateway.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "api-gateway.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "api-gateway.labels" -}}
helm.sh/chart: {{ include "api-gateway.chart" . }}
{{ include "api-gateway.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "api-gateway.selectorLabels" -}}
app.kubernetes.io/name: {{ include "api-gateway.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "api-gateway.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "api-gateway.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,9 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: vol-cfg-swaggerdoc
annotations:
checksum/config: {{ .Files.Get "spec/swagger.yaml" | indent 4 | sha256sum }}
data:
swagger.yaml: |-
{{ .Files.Get "spec/swagger.yaml" | indent 4 }}

View File

@@ -0,0 +1,75 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "api-gateway.fullname" . }}
labels:
{{- include "api-gateway.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "api-gateway.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
annotations:
checksum/config: {{ .Files.Get "spec/swagger.yaml" | indent 4 | sha256sum }}
labels:
{{- include "api-gateway.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "api-gateway.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: "SWAGGER_JSON"
value: {{ .Values.SWAGGER_JSON }}
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
initialDelaySeconds: 5
httpGet:
path: /
port: 8080
readinessProbe:
initialDelaySeconds: 5
httpGet:
path: /
port: 8080
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: configs
mountPath: /mnt/swagger.yaml
subPath: swagger.yaml
volumes:
- name: configs
configMap:
name: vol-cfg-swaggerdoc
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

View File

@@ -0,0 +1,28 @@
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "api-gateway.fullname" . }}
labels:
{{- include "api-gateway.labels" . | nindent 4 }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "api-gateway.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
{{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,61 @@
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "api-gateway.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
{{- include "api-gateway.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "api-gateway.fullname" . }}
labels:
{{- include "api-gateway.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "api-gateway.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "api-gateway.serviceAccountName" . }}
labels:
{{- include "api-gateway.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "api-gateway.fullname" . }}-test-connection"
labels:
{{- include "api-gateway.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "api-gateway.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

99
helm/swagger/values.yaml Normal file
View File

@@ -0,0 +1,99 @@
# Default values for api-gateway.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
#name: api-gateway
#repository: 172.17.0.1:5000/api-gateway
repository: swaggerapi/swagger-ui
#pullPolicy: IfNotPresent
pullPolicy: Never
# Overrides the image tag whose default is the chart appVersion.
tag: "latest"
#tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: "swagger"
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 8080
ingress:
enabled: false
className: ""
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
tls: []
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity: {}
SWAGGER_JSON: /mnt/swagger.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: vol-cfg-swaggerdoc
data:
swagger.yaml: |-
{{ .Files.Get "spec/swagger.yaml" | indent 4 }}

View File

@@ -1,6 +1,6 @@
replicaCount: 1
vault:
#vault:
serviceAccount:
create: true

4
requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
behave
allure-behave
requests
jsonschema

View File

@@ -0,0 +1,24 @@
import string
import random
def before_feature(context, feature):
context.feat = {}
context.feat['username'] = generate_username(8)
context.feat['password'] = generate_password(16)
def before_scenario(context, scenario):
context.headers = {}
context.params = {}
context.response = None
def generate_username(length):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(length))
def generate_password(length):
characters = string.ascii_letters + string.digits + string.punctuation
return ''.join(random.choice(characters) for i in range(length))

View File

@@ -0,0 +1,4 @@
{
"username": "test",
"password": "password123"
}

View File

@@ -0,0 +1,4 @@
{
"username": "test",
"password": "password123"
}

View File

@@ -0,0 +1,4 @@
{
"username": "test",
"password": "password123"
}

View File

@@ -0,0 +1,12 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"token": {
"type": "string"
}
},
"required": [
"token"
]
}

View File

@@ -0,0 +1,32 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"first_name": {
"type": "string"
},
"last_name": {
"type": "string"
},
"street_number": {
"type": "integer"
},
"street": {
"type": "string"
},
"city": {
"type": "string"
},
"postal_code": {
"type": "string"
}
},
"required": [
"first_name",
"last_name",
"street_number",
"street",
"city",
"postal_code"
]
}

View File

@@ -0,0 +1,12 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"token": {
"type": "string"
}
},
"required": [
"token"
]
}

View File

@@ -0,0 +1,88 @@
from behave import given, when, then, step
import os
import requests
import json
import jsonschema
import random
import string
@given(u'I set API url to "{url}"')
def step_impl(context, url):
context.api_base_url = url
@when(u'I Set HEADER param request content type as "{header_content_type}"')
def step_impl(context, header_content_type):
context.headers['Content-Type'] = header_content_type
@when(u'I Set HEADER param request authorization from context')
def step_impl(context):
context.headers['Authorization'] = 'Bearer ' + context.feat['token']
@then(u'I save token in context for future requests')
def step_impl(context):
context.feat['token'] = json.loads(context.response.text)['token']
@when(u'I update request body key "{key}" from context')
def step_impl(context, key):
context.params[key] = context.feat[key]
@when(u'I update request body key "{key}" to random value')
def step_impl(context, key):
context.params[key] = ''.join(random.choice(string.ascii_lowercase) for i in range(8))
@when(u'I set request Body like in "{request_body_file}"')
def step_impl(context, request_body_file):
dir_path = os.path.dirname(os.path.realpath(__file__))
with open(dir_path + request_body_file, 'r', encoding='UTF-8') as file_contents:
data = file_contents.read()
json_body = json.loads(data)
context.params = json_body
@given(u'I Set "{method}" api endpoint to "{endpoint}"')
def step_impl(context, method, endpoint):
key = method + '_URL'
context.api_endpoint = context.api_base_url + '/' + endpoint
@when(u'I send HTTP POST request')
def step_impl(context):
context.response = requests.post(url=context.api_endpoint, json=context.params,
headers=context.headers)
@when(u'I send HTTP GET request')
def step_impl(context):
context.response = requests.get(url=context.api_endpoint, headers=context.headers)
@then(u'I receive HTTP response code "{response_code}"')
def step_impl(context, response_code):
assert str(context.response.status_code) == response_code
@then(u'Response BODY is non-empty')
def step_impl(context):
assert context.response.text is not None
@then(u'Response BODY "{request_name}" is empty')
def step_impl(context, request_name):
assert context.response.text is None
@step('JSON schema should be like in "{filename}"')
def json_schema_as_in_file(context, filename):
dir_path = os.path.dirname(os.path.realpath(__file__))
with open(dir_path + filename, 'r', encoding='UTF-8') as json_schema:
data = json_schema.read()
json_body = json.loads(context.response.text)
jsonschema.validate(json_body, json.loads(data))

View File

@@ -0,0 +1,70 @@
@user-tests
Feature: Test Connected Home User Service API
Background:
Given I set API url to "http://127.0.0.1:8082/api"
@register-user-pos-1
Scenario: Register new user
Given I Set "POST" api endpoint to "register"
When I Set HEADER param request content type as "application/json"
And I set request Body like in "/../requests/user-service/register.json"
And I update request body key "username" from context
And I update request body key "password" from context
And I send HTTP POST request
Then I receive HTTP response code "201"
And Response BODY is non-empty
And JSON schema should be like in "/../responses/user-service/register_positive.json"
And I save token in context for future requests
@register-user-neg-1
Scenario: Register existing user
Given I Set "POST" api endpoint to "register"
When I Set HEADER param request content type as "application/json"
And I set request Body like in "/../requests/user-service/register.json"
And I update request body key "username" from context
And I update request body key "password" from context
And I send HTTP POST request
Then I receive HTTP response code "400"
And Response BODY is non-empty
# And JSON schema should be like in "/../responses/user-service/register_negative.json"
@login-pos-1
Scenario: Login with existing user
Given I Set "POST" api endpoint to "login"
When I Set HEADER param request content type as "application/json"
And I set request Body like in "/../requests/user-service/login.json"
And I update request body key "username" from context
And I update request body key "password" from context
And I send HTTP POST request
Then I receive HTTP response code "200"
And Response BODY is non-empty
And JSON schema should be like in "/../responses/user-service/login.json"
@login-neg-1
Scenario: Login with non-existent user
Given I Set "POST" api endpoint to "login"
When I Set HEADER param request content type as "application/json"
And I set request Body like in "/../requests/user-service/login.json"
And I update request body key "username" to random value
And I update request body key "password" to random value
And I send HTTP POST request
Then I receive HTTP response code "400"
And Response BODY is non-empty
# And JSON schema should be like in "/../responses/user-service/login.json"
@profile-pos-1
Scenario: Retrieve user profile
Given I Set "GET" api endpoint to "profile"
When I Set HEADER param request content type as "application/json"
When I Set HEADER param request authorization from context
And I set request Body like in "/../requests/user-service/profile.json"
And I send HTTP GET request
Then I receive HTTP response code "200"
And Response BODY is non-empty
And JSON schema should be like in "/../responses/user-service/profile.json"