Skip to content

Commit e76166a

Browse files
committed
added shutdown test & hbase-entrypoint.sh
1 parent 5e8201f commit e76166a

20 files changed

+1166
-339
lines changed

Cargo.nix

Lines changed: 594 additions & 275 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/crd/src/lib.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ use stackable_operator::{
1818
fragment::{self, Fragment, ValidationError},
1919
merge::{Atomic, Merge},
2020
},
21-
k8s_openapi::{api::core::v1::EnvVar, apimachinery::pkg::api::resource::Quantity, DeepMerge},
21+
k8s_openapi::{
22+
api::core::v1::{EnvVar, EnvVarSource, ObjectFieldSelector},
23+
apimachinery::pkg::api::resource::Quantity,
24+
DeepMerge,
25+
},
2226
kube::{runtime::reflector::ObjectRef, CustomResource, ResourceExt},
2327
product_config_utils::Configuration,
2428
product_logging::{self, spec::Logging},
@@ -1051,6 +1055,14 @@ impl HbaseCluster {
10511055
}
10521056
}
10531057

1058+
pub fn service_port(&self, role: &HbaseRole) -> u16 {
1059+
match role {
1060+
HbaseRole::Master => HBASE_MASTER_PORT,
1061+
HbaseRole::RegionServer => HBASE_REGIONSERVER_PORT,
1062+
_ => HBASE_REST_PORT,
1063+
}
1064+
}
1065+
10541066
/// Name of the port used by the Web UI, which depends on HTTPS usage
10551067
fn ui_port_name(&self) -> String {
10561068
if self.has_https_enabled() {
@@ -1064,20 +1076,36 @@ impl HbaseCluster {
10641076

10651077
pub fn merged_env(rolegroup_config: Option<&BTreeMap<String, String>>) -> Vec<EnvVar> {
10661078
let merged_env: Vec<EnvVar> = if let Some(rolegroup_config) = rolegroup_config {
1067-
let env_vars_from_config: BTreeMap<String, EnvVar> = rolegroup_config
1079+
let mut env_vars_from_config: Vec<EnvVar> = rolegroup_config
10681080
.iter()
1069-
.map(|(env_name, env_value)| {
1070-
(
1071-
env_name.clone(),
1072-
EnvVar {
1073-
name: env_name.clone(),
1074-
value: Some(env_value.to_owned()),
1075-
value_from: None,
1076-
},
1077-
)
1081+
.map(|(env_name, env_value)| EnvVar {
1082+
name: env_name.clone(),
1083+
value: Some(env_value.to_owned()),
1084+
value_from: None,
10781085
})
10791086
.collect();
1080-
env_vars_from_config.into_values().collect()
1087+
1088+
// Needed by the hbase-entrypoint.sh script
1089+
env_vars_from_config.push(EnvVar {
1090+
name: "NAMESPACE".to_string(),
1091+
value: None,
1092+
value_from: Some(EnvVarSource {
1093+
field_ref: Some(ObjectFieldSelector {
1094+
field_path: "metadata.namespace".to_string(),
1095+
..Default::default()
1096+
}),
1097+
..Default::default()
1098+
}),
1099+
});
1100+
1101+
// Needed by the hbase-entrypoint.sh script
1102+
env_vars_from_config.push(EnvVar {
1103+
name: "REGION_MOVER_OPTS".to_string(),
1104+
value: None,
1105+
value_from: None,
1106+
});
1107+
1108+
env_vars_from_config
10811109
} else {
10821110
vec![]
10831111
};

rust/operator-binary/src/hbase_controller.rs

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ handle_term_signal()
110110
if [ "${term_child_pid}" ]; then
111111
if [ -n "$PRE_SHUTDOWN_COMMAND" ]; then
112112
echo "Start pre-shutdown command: $PRE_SHUTDOWN_COMMAND"
113-
source "$PRE_SHUTDOWN_COMMAND"
113+
$(${PRE_SHUTDOWN_COMMAND})
114114
echo "Done pre-shutdown command"
115115
fi
116116
kill -TERM "${term_child_pid}" 2>/dev/null
@@ -853,38 +853,12 @@ fn build_rolegroup_statefulset(
853853
let mut hbase_container = ContainerBuilder::new("hbase").expect("ContainerBuilder not created");
854854
hbase_container
855855
.image_from_product_image(resolved_product_image)
856-
.command(vec![
857-
"/bin/bash".to_string(),
858-
"-x".to_string(),
859-
"-euo".to_string(),
860-
"pipefail".to_string(),
861-
"-c".to_string(),
856+
.command(vec!["/stackable/hbase/bin/hbase-entrypoint.sh".to_string()])
857+
.args(vec![
858+
hbase_role.cli_role_name(),
859+
rolegroup_ref.object_name(),
860+
hbase.service_port(hbase_role).to_string(),
862861
])
863-
.args(vec![formatdoc! {"
864-
mkdir -p {CONFIG_DIR_NAME}
865-
cp {HDFS_DISCOVERY_TMP_DIR}/hdfs-site.xml {CONFIG_DIR_NAME}
866-
cp {HDFS_DISCOVERY_TMP_DIR}/core-site.xml {CONFIG_DIR_NAME}
867-
cp {HBASE_CONFIG_TMP_DIR}/* {CONFIG_DIR_NAME}
868-
cp {HBASE_LOG_CONFIG_TMP_DIR}/{log4j_properties_file_name} {CONFIG_DIR_NAME}
869-
870-
{kerberos_container_start_commands}
871-
872-
PRE_SHUTDOWN_COMMAND={pre_shutdown_command}
873-
{HBASE_BASH_TRAP_FUNCTIONS}
874-
{remove_vector_shutdown_file_command}
875-
prepare_signal_handlers
876-
bin/hbase {hbase_role_name_in_command} start &
877-
wait_for_termination $!
878-
{create_vector_shutdown_file_command}
879-
",
880-
pre_shutdown_command=config.pre_shutdown_command(),
881-
hbase_role_name_in_command = hbase_role.cli_role_name(),
882-
kerberos_container_start_commands = kerberos_container_start_commands(hbase),
883-
remove_vector_shutdown_file_command =
884-
remove_vector_shutdown_file_command(STACKABLE_LOG_DIR),
885-
create_vector_shutdown_file_command =
886-
create_vector_shutdown_file_command(STACKABLE_LOG_DIR),
887-
}])
888862
.add_env_vars(merged_env)
889863
.add_volume_mount("hbase-config", HBASE_CONFIG_TMP_DIR)
890864
.add_volume_mount("hdfs-discovery", HDFS_DISCOVERY_TMP_DIR)

scripts/run-tests

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,18 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
9595
parser.add_argument(
9696
"--operator",
9797
help="Patch operator version in release.yaml. Format <operator>=<version>",
98-
nargs="*",
98+
action="append",
9999
type=cli_parse_operator_args,
100100
default=[],
101101
)
102102

103+
parser.add_argument(
104+
"--skip-operator",
105+
help="Skip given operator(s) when installing a release.",
106+
action="append",
107+
default=[],
108+
)
109+
103110
parser.add_argument(
104111
"--test",
105112
help="Kuttl test to run.",
@@ -138,7 +145,7 @@ def cli_parse_operator_args(args: str) -> tuple[str, str]:
138145
f"Invalid operator argument: {args}. Must be in format <operator>=<version>"
139146
)
140147
op, version = args.split("=", maxsplit=1)
141-
return (op, version)
148+
return op, version
142149

143150

144151
def cli_log_level(cli_arg: str) -> int:
@@ -179,11 +186,13 @@ def have_requirements() -> None:
179186

180187
@contextlib.contextmanager
181188
def release_file(
182-
operators: list[tuple[str, str]] = [],
189+
operators: list[tuple[str, str]], skip_ops: list[str]
183190
) -> collections.abc.Generator[str, None, None]:
184-
"""Patch release.yaml with operator versions if needed.
191+
"""Generate a (possibly modified) copy of the release.yaml file.
185192
186-
If no --operator is set, the default release file is used.
193+
Operator versions passed as --operator take precedence over the release.yaml contents.
194+
195+
Operators passed as --skip-operator are excluded from the resulting release.yaml contents.
187196
188197
If an invalid operator name is provided (i.e. one that doesn't exist in the
189198
original release file), a TestRunnerException is raised.
@@ -194,36 +203,60 @@ def release_file(
194203

195204
def _patch():
196205
release_file = os.path.join("tests", "release.yaml")
197-
# Make a copy so we can mutate it without affecting the original
198-
ops_copy = operators.copy()
206+
# A marker to validate that all ops were patched
199207
patched_release = []
200208
with open(release_file, "r") as f:
209+
patched_ops = []
201210
patch_version = ""
202211
for line in f:
203212
if patch_version:
204213
line = re.sub(":.+$", f": {patch_version}", line)
205214
patch_version = ""
206215
else:
207-
for op, version in ops_copy:
216+
for op, version in operators:
208217
if op in line:
209218
patch_version = version
210-
ops_copy.remove((op, version)) # found an operator to patch
219+
patched_ops.append(op)
211220
break
212-
patched_release.append(line)
213-
if ops_copy:
214-
# Some --operator args were not found in the release file. This is
215-
# most likely a typo and CI pipelines should terminate early in such
216-
# cases.
221+
patched_release.append(line.rstrip("\n"))
222+
223+
# Sanity test that cli didn't contain garbage that is silently discarded
224+
ops_not_patched = set([op for op, _ in operators]) - set(patched_ops)
225+
if ops_not_patched:
226+
logging.error(
227+
f"Patched operators [{', '.join(ops_not_patched)}] not found in {release_file}"
228+
)
229+
raise TestRunnerException()
230+
231+
# Filter out skip operators
232+
release_contents = []
233+
skip = False
234+
valid_skip_ops = []
235+
for line in patched_release:
236+
if skip:
237+
skip = False
238+
continue
239+
for op in skip_ops:
240+
if op in line:
241+
skip = True
242+
valid_skip_ops.append(op)
243+
break
244+
else:
245+
release_contents.append(line)
246+
# Sanity test that cli didn't contain garbage that is silently discarded
247+
ops_not_skipped = set(skip_ops) - set(valid_skip_ops)
248+
if ops_not_skipped:
217249
logging.error(
218-
f"Operators {', '.join([op for op, _ in ops_copy])} not found in {release_file}"
250+
f"Skipped operators [{', '.join(ops_not_skipped)}] not found in {release_file}"
219251
)
220252
raise TestRunnerException()
253+
221254
with tempfile.NamedTemporaryFile(
222255
mode="w",
223256
delete=False,
224257
prefix="patched",
225258
) as f:
226-
pcontents = "".join(patched_release)
259+
pcontents = "\n".join(release_contents)
227260
logging.debug(f"Writing patched release to {f.name}: {pcontents}\n")
228261
f.write(pcontents)
229262
return f.name
@@ -353,7 +386,7 @@ def main(argv) -> int:
353386
logging.basicConfig(encoding="utf-8", level=opts.log_level)
354387
have_requirements()
355388
gen_tests(opts.test_suite)
356-
with release_file(opts.operator) as f:
389+
with release_file(opts.operator, opts.skip_operator) as f:
357390
maybe_install_release(opts.skip_release, f)
358391
if opts.skip_tests:
359392
logging.info("Skip running tests.")
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
apiVersion: v1
3+
kind: LimitRange
4+
metadata:
5+
name: limit-request-ratio
6+
spec:
7+
limits:
8+
- type: "Container"
9+
maxLimitRequestRatio:
10+
cpu: 5
11+
memory: 1
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% if test_scenario['values']['openshift'] == 'true' %}
2+
# see https://github.com/stackabletech/issues/issues/566
3+
---
4+
apiVersion: kuttl.dev/v1beta1
5+
kind: TestStep
6+
commands:
7+
- script: kubectl patch namespace $NAMESPACE -p '{"metadata":{"labels":{"pod-security.kubernetes.io/enforce":"privileged"}}}'
8+
timeout: 120
9+
{% endif %}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
5+
---
6+
apiVersion: v1
7+
kind: ConfigMap
8+
metadata:
9+
name: vector-aggregator-discovery
10+
{% endif %}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
2+
---
3+
apiVersion: v1
4+
kind: ConfigMap
5+
metadata:
6+
name: vector-aggregator-discovery
7+
data:
8+
ADDRESS: {{ lookup('env', 'VECTOR_AGGREGATOR') }}
9+
{% endif %}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
apiVersion: kuttl.dev/v1beta1
3+
kind: TestAssert
4+
metadata:
5+
name: install-zk
6+
timeout: 600
7+
---
8+
apiVersion: apps/v1
9+
kind: StatefulSet
10+
metadata:
11+
name: test-zk-server-default
12+
status:
13+
readyReplicas: 1
14+
replicas: 1
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
apiVersion: zookeeper.stackable.tech/v1alpha1
3+
kind: ZookeeperCluster
4+
metadata:
5+
name: test-zk
6+
spec:
7+
image:
8+
productVersion: "{{ test_scenario['values']['zookeeper-latest'] }}"
9+
pullPolicy: IfNotPresent
10+
clusterConfig:
11+
listenerClass: "cluster-internal"
12+
{% if lookup('env', 'VECTOR_AGGREGATOR') %}
13+
vectorAggregatorConfigMapName: vector-aggregator-discovery
14+
{% endif %}
15+
servers:
16+
config:
17+
logging:
18+
enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }}
19+
roleGroups:
20+
default:
21+
replicas: 1
22+
---
23+
apiVersion: zookeeper.stackable.tech/v1alpha1
24+
kind: ZookeeperZnode
25+
metadata:
26+
name: test-znode
27+
spec:
28+
clusterRef:
29+
name: test-zk

0 commit comments

Comments
 (0)