Skip to content

Commit

Permalink
feat: Support podOverrides (#458)
Browse files Browse the repository at this point in the history
# Description

*Please add a description here. This will become the commit message of the merge request later.*
  • Loading branch information
sbernauer committed Jul 5, 2023
1 parent ab0b9f7 commit 25e5257
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- Missing CRD defaults for `status.conditions` field ([#443]).
- Support for OPA 0.51.0 ([#451]).
- Set explicit resources on all containers ([#453]).
- Support `podOverrides` ([#458]).

### Changed

Expand All @@ -32,6 +33,7 @@ All notable changes to this project will be documented in this file.
[#453]: https://github.com/stackabletech/opa-operator/pull/453
[#455]: https://github.com/stackabletech/opa-operator/pull/455
[#456]: https://github.com/stackabletech/opa-operator/pull/456
[#458]: https://github.com/stackabletech/opa-operator/pull/458

## [23.4.0] - 2023-04-17

Expand Down
35 changes: 33 additions & 2 deletions rust/crd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ use stackable_operator::{
product_config_utils::{ConfigError, Configuration},
product_logging::{self, spec::Logging},
role_utils::Role,
role_utils::RoleGroupRef,
role_utils::{RoleGroup, RoleGroupRef},
schemars::{self, JsonSchema},
status::condition::{ClusterCondition, HasStatusCondition},
};
use std::collections::BTreeMap;
use std::{collections::BTreeMap, str::FromStr};
use strum::{Display, EnumIter, EnumString};

pub const APP_NAME: &str = "opa";
Expand All @@ -29,6 +29,13 @@ pub const CONFIG_FILE: &str = "config.yaml";

#[derive(Snafu, Debug)]
pub enum Error {
#[snafu(display("the role group {role_group} is not defined"))]
CannotRetrieveOpaRoleGroup { role_group: String },
#[snafu(display("unknown role {role}"))]
UnknownOpaRole {
source: strum::ParseError,
role: String,
},
#[snafu(display("the role group [{role_group}] is missing"))]
MissingRoleGroup { role_group: String },
#[snafu(display("fragment validation failure"))]
Expand Down Expand Up @@ -237,6 +244,30 @@ pub enum OpaRole {
}

impl OpaCluster {
/// Returns a reference to the role.
pub fn role(&self, role_variant: &OpaRole) -> &Role<OpaConfigFragment> {
match role_variant {
OpaRole::Server => &self.spec.servers,
}
}

/// Returns a reference to the role group. Raises an error if the role or role group are not defined.
pub fn rolegroup(
&self,
rolegroup_ref: &RoleGroupRef<OpaCluster>,
) -> Result<&RoleGroup<OpaConfigFragment>, Error> {
let role_variant =
OpaRole::from_str(&rolegroup_ref.role).with_context(|_| UnknownOpaRoleSnafu {
role: rolegroup_ref.role.to_owned(),
})?;
let role = self.role(&role_variant);
role.role_groups
.get(&rolegroup_ref.role_group)
.with_context(|| CannotRetrieveOpaRoleGroupSnafu {
role_group: rolegroup_ref.role_group.to_owned(),
})
}

/// The name of the role-level load-balanced Kubernetes `Service`
pub fn server_role_service_name(&self) -> Option<String> {
self.metadata.name.clone()
Expand Down
25 changes: 20 additions & 5 deletions rust/operator-binary/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use snafu::{OptionExt, ResultExt, Snafu};
use stackable_opa_crd::{
Container, OpaCluster, OpaClusterStatus, OpaConfig, OpaRole, APP_NAME, OPERATOR_NAME,
};
use stackable_operator::k8s_openapi::DeepMerge;
use stackable_operator::{
builder::{
resources::ResourceRequirementsBuilder, ConfigMapBuilder, ContainerBuilder,
Expand Down Expand Up @@ -105,6 +106,8 @@ pub struct Ctx {
pub enum Error {
#[snafu(display("object does not define meta name"))]
NoName,
#[snafu(display("internal operator failure"))]
InternalOperatorFailure { source: stackable_opa_crd::Error },
#[snafu(display("failed to calculate role service name"))]
RoleServiceNameNotFound,
#[snafu(display("failed to apply role Service"))]
Expand Down Expand Up @@ -202,6 +205,7 @@ pub async fn reconcile_opa(opa: Arc<OpaCluster>, ctx: Arc<Ctx>) -> Result<Action
let opa_ref = ObjectRef::from_obj(opa.as_ref());
let client = &ctx.client;
let resolved_product_image = opa.spec.image.resolve(DOCKER_IMAGE_BASE_NAME);
let opa_role = OpaRole::Server;

let mut cluster_resources = ClusterResources::new(
APP_NAME,
Expand All @@ -217,7 +221,7 @@ pub async fn reconcile_opa(opa: Arc<OpaCluster>, ctx: Arc<Ctx>) -> Result<Action
&transform_all_roles_to_config(
opa.as_ref(),
[(
OpaRole::Server.to_string(),
opa_role.to_string(),
(
vec![
PropertyNameKind::File(CONFIG_FILE.to_string()),
Expand All @@ -235,7 +239,7 @@ pub async fn reconcile_opa(opa: Arc<OpaCluster>, ctx: Arc<Ctx>) -> Result<Action
)
.context(InvalidProductConfigSnafu)?;
let role_server_config = validated_config
.get(&OpaRole::Server.to_string())
.get(&opa_role.to_string())
.map(Cow::Borrowed)
.unwrap_or_default();

Expand Down Expand Up @@ -271,12 +275,12 @@ pub async fn reconcile_opa(opa: Arc<OpaCluster>, ctx: Arc<Ctx>) -> Result<Action
for (rolegroup_name, rolegroup_config) in role_server_config.iter() {
let rolegroup = RoleGroupRef {
cluster: opa_ref.clone(),
role: OpaRole::Server.to_string(),
role: opa_role.to_string(),
role_group: rolegroup_name.to_string(),
};

let merged_config = opa
.merged_config(&OpaRole::Server, &rolegroup)
.merged_config(&opa_role, &rolegroup)
.context(FailedToResolveConfigSnafu)?;

let rg_configmap = build_server_rolegroup_config_map(
Expand All @@ -290,6 +294,7 @@ pub async fn reconcile_opa(opa: Arc<OpaCluster>, ctx: Arc<Ctx>) -> Result<Action
let rg_daemonset = build_server_rolegroup_daemonset(
&opa,
&resolved_product_image,
&opa_role,
&rolegroup,
rolegroup_config,
&merged_config,
Expand Down Expand Up @@ -509,11 +514,17 @@ fn build_server_rolegroup_config_map(
fn build_server_rolegroup_daemonset(
opa: &OpaCluster,
resolved_product_image: &ResolvedProductImage,
opa_role: &OpaRole,
rolegroup_ref: &RoleGroupRef<OpaCluster>,
server_config: &HashMap<PropertyNameKind, BTreeMap<String, String>>,
merged_config: &OpaConfig,
sa_name: &str,
) -> Result<DaemonSet> {
let role = opa.role(opa_role);
let role_group = opa
.rolegroup(rolegroup_ref)
.context(InternalOperatorFailureSnafu)?;

let env = server_config
.get(&PropertyNameKind::Env)
.iter()
Expand Down Expand Up @@ -697,6 +708,10 @@ fn build_server_rolegroup_daemonset(
));
}

let mut pod_template = pb.build_template();
pod_template.merge_from(role.config.pod_overrides.clone());
pod_template.merge_from(role_group.config.pod_overrides.clone());

Ok(DaemonSet {
metadata: ObjectMetaBuilder::new()
.name_and_namespace(opa)
Expand All @@ -720,7 +735,7 @@ fn build_server_rolegroup_daemonset(
)),
..LabelSelector::default()
},
template: pb.build_template(),
template: pod_template,
..DaemonSetSpec::default()
}),
status: None,
Expand Down
21 changes: 21 additions & 0 deletions tests/templates/kuttl/resources/10-assert.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,24 @@ spec:
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
- name: vector
{% endif %}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: opa-server-resources-from-pod-overrides
spec:
template:
spec:
containers:
- name: opa
resources:
requests:
cpu: 210m
memory: 256Mi
limits:
cpu: 310m
memory: 256Mi
- name: bundle-builder
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
- name: vector
{% endif %}
10 changes: 10 additions & 0 deletions tests/templates/kuttl/resources/10-install-opa.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@ spec:
limit: 512Mi
logging:
enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }}
resources-from-pod-overrides:
podOverrides:
spec:
containers:
- name: opa
resources:
requests:
cpu: 210m
limits:
cpu: 310m

0 comments on commit 25e5257

Please sign in to comment.