diff --git a/.woodpecker/build.yaml b/.woodpecker/build.yaml deleted file mode 100644 index 38bf6dd..0000000 --- a/.woodpecker/build.yaml +++ /dev/null @@ -1,47 +0,0 @@ -# Build a container image -when: - event: - - push -services: - docker: - image: docker:dind - commands: - - echo "1" > /proc/sys/net/ipv4/ip_forward - - dockerd -H tcp://0.0.0.0:2375 --tls=false - privileged: true - ports: - - 2375 - - 16443 - backend_options: - kubernetes: - resources: - requests: - memory: 500Mi - cpu: 200m - limits: - memory: 1000Mi - cpu: 1000m -steps: - build: - image: git.badhouseplants.net/badhouseplants/badhouseplants-builder:555262114ea81f6f286010474527f419b56d33a3 - name: Build shoebill operator image - privileged: true - environment: - - PACKAGE_NAME=allanger/shoebill-operator - commands: - - | - if [[ "${CI_COMMIT_TAG}" ]]; then - export CUSTOM_TAG="${CI_COMMIT_TAG}"; - fi - - build-container - secrets: - - gitea_token - backend_options: - kubernetes: - resources: - requests: - memory: 500Mi - cpu: 200m - limits: - memory: 1000Mi - cpu: 1000m diff --git a/src/cmd/manifests.rs b/src/cmd/manifests.rs index 7bb5bf4..8d33536 100644 --- a/src/cmd/manifests.rs +++ b/src/cmd/manifests.rs @@ -4,8 +4,4 @@ use clap::{Args, Command, Parser, Subcommand}; pub(crate) struct ManifestsArgs { #[arg(long, short, default_value = "default")] pub(crate) namespace: String, - #[arg(long, short, default_value = "latest")] - pub(crate) tag: String, - #[arg(long, short, default_value = "shoebill")] - pub(crate) image: String, } diff --git a/src/controllers/configsets_controller.rs b/src/controllers/configsets_controller.rs index db76274..1b4636e 100644 --- a/src/controllers/configsets_controller.rs +++ b/src/controllers/configsets_controller.rs @@ -1,22 +1,15 @@ -use crate::api::v1alpha1::configsets_api::{ - ConfigSet, Input, InputWithName, TargetWithName, Templates, -}; -use core::fmt; +use crate::api::v1alpha1::configsets_api::ConfigSet; use futures::StreamExt; use handlebars::Handlebars; use k8s_openapi::api::core::v1::{ConfigMap, Secret}; -use k8s_openapi::apimachinery::pkg::apis::meta::v1::OwnerReference; -use k8s_openapi::{ByteString, NamespaceResourceScope}; +use k8s_openapi::ByteString; use kube::api::{ListParams, PostParams}; use kube::core::{Object, ObjectMeta}; use kube::error::ErrorResponse; use kube::runtime::controller::Action; -use kube::runtime::finalizer::Event as Finalizer; use kube::runtime::watcher::Config; -use kube::runtime::{finalizer, Controller}; +use kube::runtime::Controller; use kube::{Api, Client, CustomResource}; -use kube_client::core::DynamicObject; -use kube_client::{Resource, ResourceExt}; use log::*; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -25,12 +18,11 @@ use std::str::{from_utf8, Utf8Error}; use std::sync::Arc; use std::time::Duration; use thiserror::Error; - -static WATCHED_BY_SHU: &str = "badhouseplants.net/watched-by-shu"; -static SHU_FINALIZER: &str = "badhouseplants.net/shu-cleanup"; - #[derive(Error, Debug)] pub enum Error { + #[error("SerializationError: {0}")] + SerializationError(#[source] serde_json::Error), + #[error("Kube Error: {0}")] KubeError(#[source] kube::Error), @@ -39,11 +31,15 @@ pub enum Error { // so boxing this error to break cycles FinalizerError(#[source] Box>), - #[error("IllegalConfigSet: {0}")] - IllegalConfigSet(#[source] Box), + #[error("IllegalDocument")] + IllegalDocument, +} +pub type Result = std::result::Result; +impl Error { + pub fn metric_label(&self) -> String { + format!("{self:?}").to_lowercase() + } } - -pub(crate) type Result = std::result::Result; // Context for our reconciler #[derive(Clone)] @@ -53,39 +49,16 @@ pub struct Context { } async fn reconcile(csupstream: Arc, ctx: Arc) -> Result { - let ns = csupstream.namespace().unwrap(); - let confset: Api = Api::namespaced(ctx.client.clone(), &ns); - finalizer(&confset, SHU_FINALIZER, csupstream.clone(), |event| async { - info!( - "reconciling {} - {}", - csupstream.metadata.name.clone().unwrap(), - csupstream.metadata.namespace.clone().unwrap() - ); - match event { - Finalizer::Apply(doc) => match csupstream.reconcile(ctx.clone()).await { - Ok(res) => { - info!("reconciled successfully"); - Ok(res) - } - Err(err) => { - error!("reconciliation has failed with error: {}", err); - Err(err) - } - }, - Finalizer::Cleanup(doc) => match csupstream.cleanup(ctx.clone()).await { - Ok(res) => { - info!("cleaned up successfully"); - Ok(res) - } - Err(err) => { - error!("cleanup has failed with error: {}", err); - Err(err) - } - }, - } - }) - .await - .map_err(|e| Error::FinalizerError(Box::new(e))) + let cs = csupstream.clone(); + info!( + "reconciling {} - {}", + cs.metadata.name.clone().unwrap(), + cs.metadata.namespace.clone().unwrap() + ); + match cs.metadata.deletion_timestamp { + Some(_) => return cs.cleanup(ctx).await, + None => return cs.reconcile(ctx).await, + } } /// Initialize the controller and shared state (given the crd is installed) @@ -112,282 +85,6 @@ fn error_policy(doc: Arc, error: &Error, ctx: Arc) -> Action Action::requeue(Duration::from_secs(5 * 60)) } -fn get_secret_api(client: Client, namespace: String) -> Api { - Api::namespaced(client, &namespace) -} - -fn get_configmap_api(client: Client, namespace: String) -> Api { - Api::namespaced(client, &namespace) -} - -async fn gather_inputs( - client: Client, - namespace: String, - inputs: Vec, -) -> Result> { - let mut result: HashMap = HashMap::new(); - for i in inputs { - info!("populating data from input {}", i.name); - match i.from.kind { - crate::api::v1alpha1::configsets_api::Kinds::Secret => { - let secret: String = match get_secret_api(client.clone(), namespace.clone()) - .get(&i.from.name) - .await - { - Ok(s) => { - let data = s.data.clone().unwrap(); - let value = match data.get(i.from.key.as_str()) { - Some(data) => match from_utf8(&data.0) { - Ok(data) => data, - Err(err) => return Err(Error::IllegalConfigSet(Box::from(err))), - }, - None => { - return Err(Error::IllegalConfigSet(Box::from(format!( - "value is not set for the key: {}", - i.from.key - )))) - } - }; - value.to_string() - } - Err(err) => { - error!("{err}"); - return Err(Error::KubeError(err)); - } - }; - result.insert(i.from.key, secret); - } - crate::api::v1alpha1::configsets_api::Kinds::ConfigMap => { - let configmap: String = match get_configmap_api(client.clone(), namespace.clone()) - .get(&i.from.name) - .await - { - Ok(cm) => { - let data = cm.data.unwrap(); - let value = match data.get(i.from.key.as_str()) { - Some(data) => data, - None => { - return Err(Error::IllegalConfigSet(Box::from(format!( - "value is not set for the key: {}", - i.from.key - )))) - } - }; - value.to_string() - } - Err(err) => { - error!("{err}"); - return Err(Error::KubeError(err)); - } - }; - result.insert(i.name, configmap); - } - } - } - Ok(result) -} - -async fn gather_targets( - client: Client, - namespace: String, - targets: Vec, - owner_reference: Vec, -) -> Result<(HashMap, HashMap)> { - let mut target_secrets: HashMap = HashMap::new(); - let mut target_configmaps: HashMap = HashMap::new(); - for target in targets { - match target.target.kind { - crate::api::v1alpha1::configsets_api::Kinds::Secret => { - let api = get_secret_api(client.clone(), namespace.clone()); - match api.get_opt(&target.target.name).await { - Ok(sec_opt) => match sec_opt { - Some(sec) => target_secrets.insert(target.name, sec), - None => { - let empty_data: BTreeMap = BTreeMap::new(); - let new_secret: Secret = Secret { - data: Some(empty_data), - metadata: ObjectMeta { - name: Some(target.target.name), - namespace: Some(namespace.clone()), - owner_references: Some(owner_reference.clone()), - ..Default::default() - }, - ..Default::default() - }; - match api.create(&PostParams::default(), &new_secret).await { - Ok(sec) => target_secrets.insert(target.name, sec), - Err(err) => { - error!("{err}"); - return Err(Error::KubeError(err)); - } - } - } - }, - Err(err) => { - error!("{err}"); - return Err(Error::KubeError(err)); - } - }; - } - crate::api::v1alpha1::configsets_api::Kinds::ConfigMap => { - let api = get_configmap_api(client.clone(), namespace.clone()); - match api.get_opt(&target.target.name).await { - Ok(cm_opt) => match cm_opt { - Some(cm) => target_configmaps.insert(target.name, cm), - None => { - let empty_data: BTreeMap = BTreeMap::new(); - let new_configmap: ConfigMap = ConfigMap { - data: Some(empty_data), - metadata: ObjectMeta { - name: Some(target.target.name), - namespace: Some(namespace.clone()), - owner_references: Some(owner_reference.clone()), - ..Default::default() - }, - ..Default::default() - }; - match api.create(&PostParams::default(), &new_configmap).await { - Ok(cm) => target_configmaps.insert(target.name, cm), - Err(err) => { - error!("{err}"); - return Err(Error::KubeError(err)); - } - } - } - }, - Err(err) => { - error!("{err}"); - return Err(Error::KubeError(err)); - } - }; - } - } - } - Ok((target_secrets, target_configmaps)) -} - -fn build_owner_refenerce(object: ConfigSet) -> Vec { - let owner_reference = OwnerReference { - api_version: ConfigSet::api_version(&()).to_string(), - kind: ConfigSet::kind(&()).to_string(), - name: object.metadata.name.unwrap(), - uid: object.metadata.uid.unwrap(), - ..Default::default() - }; - vec![owner_reference] -} - -fn build_templates( - templates: Vec, - target_secrets: &mut HashMap, - target_configmaps: &mut HashMap, - targets: Vec, - inputs: HashMap, - confset_name: String, -) -> Result<()> { - for template in templates { - let reg = Handlebars::new(); - info!("building template {}", template.name); - let var = match reg.render_template(template.template.as_str(), &inputs) { - Ok(var) => var, - Err(err) => return Err(Error::IllegalConfigSet(Box::from(err))), - }; - - let target = match targets.iter().find(|target| target.name == template.target) { - Some(target) => target, - None => { - return Err(Error::IllegalConfigSet(Box::from(format!( - "target not found {}", - template.target - )))); - } - }; - - match target.target.kind { - crate::api::v1alpha1::configsets_api::Kinds::Secret => { - let sec = target_secrets.get_mut(&template.target).unwrap(); - let mut byte_var: ByteString = ByteString::default(); - byte_var.0 = var.as_bytes().to_vec(); - - let mut existing_data = match sec.clone().data { - Some(sec) => sec, - None => BTreeMap::new(), - }; - existing_data.insert(template.name, byte_var); - sec.data = Some(existing_data); - let mut existing_annotations = match sec.metadata.annotations.clone() { - Some(ann) => ann, - None => BTreeMap::new(), - }; - existing_annotations.insert(WATCHED_BY_SHU.to_string(), confset_name.clone()); - sec.metadata.annotations = Some(existing_annotations); - } - crate::api::v1alpha1::configsets_api::Kinds::ConfigMap => { - let cm = target_configmaps.get_mut(&template.target).unwrap(); - let mut existing_data = match cm.clone().data { - Some(cm) => cm, - None => BTreeMap::new(), - }; - existing_data.insert(template.name, var); - cm.data = Some(existing_data); - let mut existing_annotations = match cm.metadata.annotations.clone() { - Some(ann) => ann, - None => BTreeMap::new(), - }; - existing_annotations.insert(WATCHED_BY_SHU.to_string(), confset_name.clone()); - cm.metadata.annotations = Some(existing_annotations); - } - } - } - Ok(()) -} - -fn cleanup_templates( - templates: Vec, - target_secrets: &mut HashMap, - target_configmaps: &mut HashMap, - targets: Vec, -) -> Result<()> { - for template in templates { - info!("cleaning template {}", template.name); - let target = match targets.iter().find(|target| target.name == template.target) { - Some(target) => target, - None => { - return Err(Error::IllegalConfigSet(Box::from(format!( - "target not found {}", - template.target - )))); - } - }; - - match target.target.kind { - crate::api::v1alpha1::configsets_api::Kinds::Secret => { - let sec = target_secrets.get_mut(&template.target).unwrap(); - if let Some(mut existing_data) = sec.clone().data { - existing_data.remove(&template.name); - sec.data = Some(existing_data) - } - if let Some(mut existing_annotations) = sec.metadata.clone().annotations { - existing_annotations.remove(WATCHED_BY_SHU); - sec.metadata.annotations = Some(existing_annotations); - } - } - crate::api::v1alpha1::configsets_api::Kinds::ConfigMap => { - let cm = target_configmaps.get_mut(&template.target).unwrap(); - if let Some(mut existing_data) = cm.clone().data { - existing_data.remove(&template.name); - cm.data = Some(existing_data); - } - if let Some(mut existing_annotations) = cm.metadata.clone().annotations { - existing_annotations.remove(WATCHED_BY_SHU); - cm.metadata.annotations = Some(existing_annotations); - } - } - } - } - Ok(()) -} - impl ConfigSet { // Reconcile (for non-finalizer related changes) async fn reconcile(&self, ctx: Arc) -> Result { @@ -396,36 +93,170 @@ impl ConfigSet { * Then use them to build new values with templates * And then write those values to targets */ + let mut inputs: HashMap = HashMap::new(); + for input in self.spec.inputs.clone() { + info!("populating data from input {}", input.name); + match input.from.kind { + crate::api::v1alpha1::configsets_api::Kinds::Secret => { + let secrets: Api = Api::namespaced( + ctx.client.clone(), + self.metadata.namespace.clone().unwrap().as_str(), + ); + let secret: String = match secrets.get(&input.from.name).await { + Ok(s) => from_utf8(&s.data.clone().unwrap()[input.from.key.as_str()].0) + .unwrap() + .to_string(), + Err(err) => { + error!("{err}"); + return Err(Error::KubeError(err)); + } + }; + inputs.insert(input.from.key, secret); + } + crate::api::v1alpha1::configsets_api::Kinds::ConfigMap => { + let configmaps: Api = Api::namespaced( + ctx.client.clone(), + self.metadata.namespace.clone().unwrap().as_str(), + ); + let configmap: String = match configmaps.get(&input.from.name).await { + Ok(cm) => { + let data = &cm.data.unwrap()[input.from.key.as_str()]; + data.to_string() + } + Err(err) => { + error!("{err}"); + return Err(Error::KubeError(err)); + } + }; + inputs.insert(input.name, configmap); + } + } + } - let inputs: HashMap = gather_inputs( - ctx.client.clone(), - self.metadata.namespace.clone().unwrap(), - self.spec.inputs.clone(), - ) - .await?; + let mut target_secrets: HashMap = HashMap::new(); + let mut target_configmaps: HashMap = HashMap::new(); - let owner_reference = build_owner_refenerce(self.clone()); + for target in self.spec.targets.clone() { + match target.target.kind { + crate::api::v1alpha1::configsets_api::Kinds::Secret => { + let secrets: Api = Api::namespaced( + ctx.client.clone(), + self.metadata.namespace.clone().unwrap().as_str(), + ); + match secrets.get_opt(&target.target.name).await { + Ok(sec_opt) => match sec_opt { + Some(sec) => target_secrets.insert(target.name, sec), + None => { + let empty_data: BTreeMap = BTreeMap::new(); + let new_secret: Secret = Secret { + data: Some(empty_data), + metadata: ObjectMeta { + name: Some(target.target.name), + namespace: self.metadata.namespace.clone(), + ..Default::default() + }, + ..Default::default() + }; + match secrets.create(&PostParams::default(), &new_secret).await { + Ok(sec) => target_secrets.insert(target.name, sec), + Err(err) => { + error!("{err}"); + return Err(Error::KubeError(err)); + } + } + } + }, + Err(err) => { + error!("{err}"); + return Err(Error::KubeError(err)); + } + }; + } + crate::api::v1alpha1::configsets_api::Kinds::ConfigMap => { + let configmaps: Api = Api::namespaced( + ctx.client.clone(), + self.metadata.namespace.clone().unwrap().as_str(), + ); + match configmaps.get_opt(&target.target.name).await { + Ok(cm_opt) => match cm_opt { + Some(cm) => target_configmaps.insert(target.name, cm), + None => { + let empty_data: BTreeMap = BTreeMap::new(); + let new_configmap: ConfigMap = ConfigMap { + data: Some(empty_data), + metadata: ObjectMeta { + name: Some(target.target.name), + namespace: self.metadata.namespace.clone(), + ..Default::default() + }, + ..Default::default() + }; + match configmaps + .create(&PostParams::default(), &new_configmap) + .await + { + Ok(cm) => target_configmaps.insert(target.name, cm), + Err(err) => { + error!("{err}"); + return Err(Error::KubeError(err)); + } + } + } + }, + Err(err) => { + error!("{err}"); + return Err(Error::KubeError(err)); + } + }; + } + } + } - let (mut target_secrets, mut target_configmaps) = gather_targets( - ctx.client.clone(), - self.metadata.namespace.clone().unwrap(), - self.spec.targets.clone(), - owner_reference, - ) - .await?; + let mut templates: HashMap = HashMap::new(); + for template in self.spec.templates.clone() { + let reg = Handlebars::new(); + info!("building template {}", template.name); + let var = reg + .render_template(template.template.as_str(), &inputs) + .unwrap(); + match self + .spec + .targets + .iter() + .find(|target| target.name == template.target) + .unwrap() + .target + .kind + { + crate::api::v1alpha1::configsets_api::Kinds::Secret => { + let sec = target_secrets.get_mut(&template.target).unwrap(); + let mut byte_var: ByteString = ByteString::default(); + byte_var.0 = var.as_bytes().to_vec(); - build_templates( - self.spec.templates.clone(), - &mut target_secrets, - &mut target_configmaps, - self.spec.targets.clone(), - inputs.clone(), - self.metadata.name.clone().unwrap(), - )?; + let mut existing_data = match sec.clone().data { + Some(sec) => sec, + None => BTreeMap::new(), + }; + existing_data.insert(template.name, byte_var); + sec.data = Some(existing_data); + } + crate::api::v1alpha1::configsets_api::Kinds::ConfigMap => { + let cm = target_configmaps.get_mut(&template.target).unwrap(); + let mut existing_data = match cm.clone().data { + Some(cm) => cm, + None => BTreeMap::new(), + }; + existing_data.insert(template.name, var); + cm.data = Some(existing_data); + } + } + } for (_, value) in target_secrets { - let secrets = - get_secret_api(ctx.client.clone(), self.metadata.namespace.clone().unwrap()); + let secrets: Api = Api::namespaced( + ctx.client.clone(), + self.metadata.namespace.clone().unwrap().as_str(), + ); match secrets .replace( value.metadata.name.clone().unwrap().as_str(), @@ -444,8 +275,10 @@ impl ConfigSet { }; } for (_, value) in target_configmaps { - let configmaps = - get_configmap_api(ctx.client.clone(), self.metadata.namespace.clone().unwrap()); + let configmaps: Api = Api::namespaced( + ctx.client.clone(), + self.metadata.namespace.clone().unwrap().as_str(), + ); match configmaps .replace( value.metadata.name.clone().unwrap().as_str(), @@ -468,69 +301,6 @@ impl ConfigSet { // Finalizer cleanup (the object was deleted, ensure nothing is orphaned) async fn cleanup(&self, ctx: Arc) -> Result { - let inputs: HashMap = gather_inputs( - ctx.client.clone(), - self.metadata.namespace.clone().unwrap(), - self.spec.inputs.clone(), - ) - .await?; - - let owner_reference = build_owner_refenerce(self.clone()); - - let (mut target_secrets, mut target_configmaps) = gather_targets( - ctx.client.clone(), - self.metadata.namespace.clone().unwrap(), - self.spec.targets.clone(), - owner_reference, - ) - .await?; - cleanup_templates( - self.spec.templates.clone(), - &mut target_secrets, - &mut target_configmaps, - self.spec.targets.clone(), - )?; - - for (_, value) in target_secrets { - let secrets = - get_secret_api(ctx.client.clone(), self.metadata.namespace.clone().unwrap()); - match secrets - .replace( - value.metadata.name.clone().unwrap().as_str(), - &PostParams::default(), - &value, - ) - .await - { - Ok(sec) => { - info!("secret {} is updated", sec.metadata.name.unwrap()); - } - Err(err) => { - error!("{}", err); - return Err(Error::KubeError(err)); - } - }; - } - for (_, value) in target_configmaps { - let configmaps = - get_configmap_api(ctx.client.clone(), self.metadata.namespace.clone().unwrap()); - match configmaps - .replace( - value.metadata.name.clone().unwrap().as_str(), - &PostParams::default(), - &value, - ) - .await - { - Ok(sec) => { - info!("secret {} is updated", sec.metadata.name.unwrap()); - } - Err(err) => { - error!("{}", err); - return Err(Error::KubeError(err)); - } - }; - } Ok::(Action::await_change()) } } diff --git a/src/helpers/manifests.rs b/src/helpers/manifests.rs index d8644be..05dfd88 100644 --- a/src/helpers/manifests.rs +++ b/src/helpers/manifests.rs @@ -12,7 +12,7 @@ use kube::{core::ObjectMeta, CustomResourceExt, ResourceExt}; use crate::api::v1alpha1::configsets_api::ConfigSet; -pub fn generate_kube_manifests(namespace: String, image: String, image_tag: String) { +pub fn generate_kube_manifests(namespace: String) { print!("---\n{}", serde_yaml::to_string(&ConfigSet::crd()).unwrap()); print!( "---\n{}", @@ -29,12 +29,7 @@ pub fn generate_kube_manifests(namespace: String, image: String, image_tag: Stri print!( "---\n{}", - serde_yaml::to_string(&prepare_deployment( - namespace.clone(), - image.clone(), - image_tag.clone() - )) - .unwrap() + serde_yaml::to_string(&prepare_deployment(namespace.clone())).unwrap() ) } @@ -124,7 +119,7 @@ fn prepare_cluster_role_binding(namespace: String) -> ClusterRoleBinding { } } -fn prepare_deployment(namespace: String, image: String, image_tag: String) -> Deployment { +fn prepare_deployment(namespace: String) -> Deployment { let mut labels: BTreeMap = BTreeMap::new(); labels.insert("container".to_string(), "shoebill-controller".to_string()); @@ -150,8 +145,8 @@ fn prepare_deployment(namespace: String, image: String, image_tag: String) -> De containers: vec![Container { command: Some(vec!["/shoebill".to_string()]), args: Some(vec!["controller".to_string()]), - image: Some(format!("{}:{}", image, image_tag)), - image_pull_policy: Some("IfNotPresent".to_string()), + image: Some("shoebill".to_string()), + image_pull_policy: Some("Never".to_string()), name: "shoebill-controller".to_string(), env: Some(vec![EnvVar { name: "RUST_LOG".to_string(), diff --git a/src/main.rs b/src/main.rs index a8cf5d9..82f579e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,11 +25,9 @@ async fn main() -> anyhow::Result<()> { let cli = Cli::parse(); match &cli.command { - Commands::Manifests(args) => helpers::manifests::generate_kube_manifests( - args.namespace.clone(), - args.image.clone(), - args.tag.clone(), - ), + Commands::Manifests(args) => { + helpers::manifests::generate_kube_manifests(args.namespace.clone()) + } Commands::Controller(args) => { // Initiatilize Kubernetes controller state let controller = configsets_controller::setup(); diff --git a/tests/test.pl b/tests/test.pl deleted file mode 100755 index 5b6d7c6..0000000 --- a/tests/test.pl +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/env sh - -# Run shoebill generate and apply -TAG=$(git rev-parse HEAD) -IMAGE="git.badhouseplants.net/allanger/shoebill-operator" -NAMESPACE="test-shoebill-operator" - -kubectl create namespace $NAMESPACE -shoebill manifests -i $IMAGE -t $TAG -n $NAMESPACE > /tmp/manifests.yaml -kubectl apply -f /tmp/manifests.yaml -kubectl rollout status -n $NAMESPACE deployment shoebill-controller - -kubectl delete -f /tmp/manifests.yaml -kubectl delete namespace $NAMESPACE diff --git a/tests/manifests/configmap.yaml b/yaml/example/configmap.yaml similarity index 100% rename from tests/manifests/configmap.yaml rename to yaml/example/configmap.yaml diff --git a/tests/manifests/example.yaml b/yaml/example/example.yaml similarity index 85% rename from tests/manifests/example.yaml rename to yaml/example/example.yaml index d347abe..f3aa3f2 100644 --- a/tests/manifests/example.yaml +++ b/yaml/example/example.yaml @@ -9,16 +9,7 @@ spec: target: kind: Secret name: app-connection-string - - name: existing-target - target: - kind: Secret - name: database-secret inputs: - - name: PROTO - from: - kind: ConfigMap - name: database-configmap - key: PROTOCOL - name: PASSWORD from: kind: Secret @@ -34,13 +25,15 @@ spec: kind: Secret name: database-secret key: DATABASE + - name: PROTO + from: + kind: ConfigMap + name: database-configmap + key: PROTOCOL templates: - name: CONNECTION template: "{{ PROTO }}:{{ USERNAME }}:{{ PASSWORD }}/{{ DATABASE }}" target: app-connection-string - - name: EXISTING - template: TEST - target: existing-target - name: IS_POSTGRES template: | {{#if (eq PROTO "postgresql") }} diff --git a/tests/manifests/secret.yaml b/yaml/example/secret.yaml similarity index 100% rename from tests/manifests/secret.yaml rename to yaml/example/secret.yaml