summaryrefslogtreecommitdiffstats
path: root/src/test/mgr
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-21 11:54:28 +0000
commite6918187568dbd01842d8d1d2c808ce16a894239 (patch)
tree64f88b554b444a49f656b6c656111a145cbbaa28 /src/test/mgr
parentInitial commit. (diff)
downloadceph-upstream/18.2.2.tar.xz
ceph-upstream/18.2.2.zip
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--src/test/mgr/CMakeLists.txt21
-rwxr-xr-xsrc/test/mgr/mgr-dashboard-smoke.sh81
-rw-r--r--src/test/mgr/test_mgrcap.cc300
-rw-r--r--src/test/mgr/test_ttlcache.cc70
4 files changed, 472 insertions, 0 deletions
diff --git a/src/test/mgr/CMakeLists.txt b/src/test/mgr/CMakeLists.txt
new file mode 100644
index 000000000..169243824
--- /dev/null
+++ b/src/test/mgr/CMakeLists.txt
@@ -0,0 +1,21 @@
+# unittest_mgr_mgrcap
+add_executable(unittest_mgr_mgrcap
+ test_mgrcap.cc
+ $<TARGET_OBJECTS:mgr_cap_obj>)
+add_ceph_unittest(unittest_mgr_mgrcap)
+target_link_libraries(unittest_mgr_mgrcap global)
+
+# unittest_mgr_ttlcache
+add_executable(unittest_mgr_ttlcache test_ttlcache.cc)
+add_ceph_unittest(unittest_mgr_ttlcache)
+target_link_libraries(unittest_mgr_ttlcache
+ Python3::Python ${CMAKE_DL_LIBS} ${GSSAPI_LIBRARIES})
+
+#scripts
+if(WITH_MGR_DASHBOARD_FRONTEND)
+ if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm|ARM")
+ add_ceph_test(mgr-dashboard-frontend-unittests ${CMAKE_SOURCE_DIR}/src/pybind/mgr/dashboard/run-frontend-unittests.sh)
+ endif(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|AARCH64|arm|ARM")
+
+ add_ceph_test(mgr-dashboard-smoke.sh ${CMAKE_CURRENT_SOURCE_DIR}/mgr-dashboard-smoke.sh)
+endif(WITH_MGR_DASHBOARD_FRONTEND)
diff --git a/src/test/mgr/mgr-dashboard-smoke.sh b/src/test/mgr/mgr-dashboard-smoke.sh
new file mode 100755
index 000000000..f50bd99c9
--- /dev/null
+++ b/src/test/mgr/mgr-dashboard-smoke.sh
@@ -0,0 +1,81 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2014,2015,2017 Red Hat <contact@redhat.com>
+# Copyright (C) 2018 SUSE LLC
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Library Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Library Public License for more details.
+#
+source $(dirname $0)/../detect-build-env-vars.sh
+source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
+
+mon_port=$(get_unused_port)
+dashboard_port=$((mon_port+1))
+
+function run() {
+ local dir=$1
+ shift
+
+ export CEPH_MON=127.0.0.1:$mon_port
+ export CEPH_ARGS
+ CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
+ CEPH_ARGS+="--mon-initial-members=a --mon-host=$MON "
+ CEPH_ARGS+="--mgr-initial-modules=dashboard "
+ CEPH_ARGS+="--mon-host=$CEPH_MON"
+
+ setup $dir || return 1
+ TEST_dashboard $dir || return 1
+ teardown $dir || return 1
+}
+
+function TEST_dashboard() {
+ local dir=$1
+ shift
+
+ run_mon $dir a || return 1
+ timeout 30 ceph mon stat || return 1
+ ceph config-key set mgr/dashboard/x/server_port $dashboard_port
+ MGR_ARGS+="--mgr_module_path=${CEPH_ROOT}/src/pybind/mgr "
+ run_mgr $dir x ${MGR_ARGS} || return 1
+
+ tries=0
+ while [[ $tries < 30 ]] ; do
+ if [ $(ceph status -f json | jq .mgrmap.available) = "true" ]
+ then
+ break
+ fi
+ tries=$((tries+1))
+ sleep 1
+ done
+
+ DASHBOARD_ADMIN_SECRET_FILE="/tmp/dashboard-admin-secret.txt"
+ printf 'admin' > "${DASHBOARD_ADMIN_SECRET_FILE}"
+ ceph_adm dashboard ac-user-create admin -i "${DASHBOARD_ADMIN_SECRET_FILE}" --force-password
+
+ tries=0
+ while [[ $tries < 30 ]] ; do
+ if curl -c $dir/cookiefile -X POST -d '{"username":"admin","password":"admin"}' http://127.0.0.1:$dashboard_port/api/auth
+ then
+ if curl -b $dir/cookiefile -s http://127.0.0.1:$dashboard_port/api/summary | \
+ jq '.health.overall_status' | grep HEALTH_
+ then
+ break
+ fi
+ fi
+ tries=$((tries+1))
+ sleep 0.5
+ done
+}
+
+main mgr-dashboard-smoke "$@"
+
+# Local Variables:
+# compile-command: "cd ../.. ; make -j4 TESTS=test/mgr/mgr-dashboard-smoke.sh check"
+# End:
diff --git a/src/test/mgr/test_mgrcap.cc b/src/test/mgr/test_mgrcap.cc
new file mode 100644
index 000000000..279e0c28e
--- /dev/null
+++ b/src/test/mgr/test_mgrcap.cc
@@ -0,0 +1,300 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2012 Inktank
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include <iostream>
+
+#include "include/stringify.h"
+#include "mgr/MgrCap.h"
+
+#include "gtest/gtest.h"
+
+using namespace std;
+
+const char *parse_good[] = {
+
+ // MgrCapMatch
+ "allow *",
+ "allow r",
+ "allow rwx",
+ "allow r",
+ " allow rwx",
+ "allow rwx ",
+ " allow rwx ",
+ " allow\t rwx ",
+ "\tallow\nrwx\t",
+ "allow service=foo x",
+ "allow service=\"froo\" x",
+ "allow profile read-only",
+ "allow profile read-write",
+ "allow profile \"rbd-read-only\", allow *",
+ "allow command \"a b c\"",
+ "allow command abc",
+ "allow command abc with arg=foo",
+ "allow command abc with arg=foo arg2=bar",
+ "allow command abc with arg=foo arg2=bar",
+ "allow command abc with arg=foo arg2 prefix bar arg3 prefix baz",
+ "allow command abc with arg=foo arg2 prefix \"bar bingo\" arg3 prefix baz",
+ "allow command abc with arg regex \"^[0-9a-z.]*$\"",
+ "allow command abc with arg regex \"\(invaluid regex\"",
+ "allow service foo x",
+ "allow service foo x; allow service bar x",
+ "allow service foo w ;allow service bar x",
+ "allow service foo w , allow service bar x",
+ "allow service foo r , allow service bar x",
+ "allow service foo_foo r, allow service bar r",
+ "allow service foo-foo r, allow service bar r",
+ "allow service \" foo \" w, allow service bar r",
+ "allow module foo x",
+ "allow module=foo x",
+ "allow module foo_foo r",
+ "allow module \" foo \" w",
+ "allow module foo with arg1=value1 x",
+ "allow command abc with arg=foo arg2=bar, allow service foo r",
+ "allow command abc.def with arg=foo arg2=bar, allow service foo r",
+ "allow command \"foo bar\" with arg=\"baz\"",
+ "allow command \"foo bar\" with arg=\"baz.xx\"",
+ "allow command \"foo bar\" with arg = \"baz.xx\"",
+ "profile crash",
+ "profile osd",
+ "profile mds",
+ "profile rbd pool=ABC namespace=NS",
+ "profile \"rbd-read-only\", profile crash",
+ "allow * network 1.2.3.4/24",
+ "allow * network ::1/128",
+ "allow * network [aa:bb::1]/128",
+ "allow service=foo x network 1.2.3.4/16",
+ "allow command abc network 1.2.3.4/8",
+ "profile crash network 1.2.3.4/32",
+ "allow profile crash network 1.2.3.4/32",
+ 0
+};
+
+TEST(MgrCap, ParseGood) {
+ for (int i=0; parse_good[i]; ++i) {
+ string str = parse_good[i];
+ MgrCap cap;
+ std::cout << "Testing good input: '" << str << "'" << std::endl;
+ ASSERT_TRUE(cap.parse(str, &cout));
+ std::cout << " -> " << cap
+ << std::endl;
+ }
+}
+
+// these should stringify to the input value
+const char *parse_identity[] = {
+ "allow *",
+ "allow r",
+ "allow rwx",
+ "allow service foo x",
+ "profile crash",
+ "profile rbd-read-only, allow *",
+ "profile rbd namespace=NS pool=ABC",
+ "allow command abc",
+ "allow command \"a b c\"",
+ "allow command abc with arg=foo",
+ "allow command abc with arg=foo arg2=bar",
+ "allow command abc with arg=foo arg2=bar",
+ "allow command abc with arg=foo arg2 prefix bar arg3 prefix baz",
+ "allow command abc with arg=foo arg2 prefix \"bar bingo\" arg3 prefix baz",
+ "allow service foo x",
+ "allow service foo x, allow service bar x",
+ "allow service foo w, allow service bar x",
+ "allow service foo r, allow service bar x",
+ "allow service foo_foo r, allow service bar r",
+ "allow service foo-foo r, allow service bar r",
+ "allow service \" foo \" w, allow service bar r",
+ "allow module foo x",
+ "allow module \" foo_foo \" r",
+ "allow module foo with arg1=value1 x",
+ "allow command abc with arg=foo arg2=bar, allow service foo r",
+ 0
+};
+
+TEST(MgrCap, ParseIdentity)
+{
+ for (int i=0; parse_identity[i]; ++i) {
+ string str = parse_identity[i];
+ MgrCap cap;
+ std::cout << "Testing good input: '" << str << "'" << std::endl;
+ ASSERT_TRUE(cap.parse(str, &cout));
+ string out = stringify(cap);
+ ASSERT_EQ(out, str);
+ }
+}
+
+const char *parse_bad[] = {
+ "allow r foo",
+ "allow*",
+ "foo allow *",
+ "profile foo rwx",
+ "profile",
+ "profile foo bar rwx",
+ "allow profile foo rwx",
+ "allow profile",
+ "allow profile foo bar rwx",
+ "allow service bar",
+ "allow command baz x",
+ "allow r w",
+ "ALLOW r",
+ "allow rwx,",
+ "allow rwx x",
+ "allow r pool foo r",
+ "allow wwx pool taco",
+ "allow wwx pool taco^funny&chars",
+ "allow rwx pool 'weird name''",
+ "allow rwx object_prefix \"beforepool\" pool weird",
+ "allow rwx auid 123 pool asdf",
+ "allow command foo a prefix b",
+ "allow command foo with a prefixb",
+ "allow command foo with a = prefix b",
+ "allow command foo with a prefix b c",
+ 0
+};
+
+TEST(MgrCap, ParseBad) {
+ for (int i=0; parse_bad[i]; ++i) {
+ string str = parse_bad[i];
+ MgrCap cap;
+ std::cout << "Testing bad input: '" << str << "'" << std::endl;
+ ASSERT_FALSE(cap.parse(str, &cout));
+ }
+}
+
+TEST(MgrCap, AllowAll) {
+ MgrCap cap;
+ ASSERT_FALSE(cap.is_allow_all());
+
+ ASSERT_TRUE(cap.parse("allow r", nullptr));
+ ASSERT_FALSE(cap.is_allow_all());
+ cap.grants.clear();
+
+ ASSERT_TRUE(cap.parse("allow w", nullptr));
+ ASSERT_FALSE(cap.is_allow_all());
+ cap.grants.clear();
+
+ ASSERT_TRUE(cap.parse("allow x", nullptr));
+ ASSERT_FALSE(cap.is_allow_all());
+ cap.grants.clear();
+
+ ASSERT_TRUE(cap.parse("allow rwx", nullptr));
+ ASSERT_FALSE(cap.is_allow_all());
+ cap.grants.clear();
+
+ ASSERT_TRUE(cap.parse("allow rw", nullptr));
+ ASSERT_FALSE(cap.is_allow_all());
+ cap.grants.clear();
+
+ ASSERT_TRUE(cap.parse("allow rx", nullptr));
+ ASSERT_FALSE(cap.is_allow_all());
+ cap.grants.clear();
+
+ ASSERT_TRUE(cap.parse("allow wx", nullptr));
+ ASSERT_FALSE(cap.is_allow_all());
+ cap.grants.clear();
+
+ ASSERT_TRUE(cap.parse("allow *", nullptr));
+ ASSERT_TRUE(cap.is_allow_all());
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
+ true, {}));
+
+ MgrCap cap2;
+ ASSERT_FALSE(cap2.is_allow_all());
+ cap2.set_allow_all();
+ ASSERT_TRUE(cap2.is_allow_all());
+}
+
+TEST(MgrCap, Network) {
+ MgrCap cap;
+ bool r = cap.parse("allow * network 192.168.0.0/16, allow * network 10.0.0.0/8", nullptr);
+ ASSERT_TRUE(r);
+
+ entity_addr_t a, b, c;
+ a.parse("10.1.2.3");
+ b.parse("192.168.2.3");
+ c.parse("192.167.2.3");
+
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
+ true, a));
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
+ true, b));
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "foo", "", "asdf", {}, true, true,
+ true, c));
+}
+
+TEST(MgrCap, CommandRegEx) {
+ MgrCap cap;
+ ASSERT_FALSE(cap.is_allow_all());
+ ASSERT_TRUE(cap.parse("allow command abc with arg regex \"^[0-9a-z.]*$\"",
+ nullptr));
+
+ EntityName name;
+ name.from_str("osd.123");
+ ASSERT_TRUE(cap.is_capable(nullptr, name, "", "", "abc",
+ {{"arg", "12345abcde"}}, true, true, true, {}));
+ ASSERT_FALSE(cap.is_capable(nullptr, name, "", "", "abc", {{"arg", "~!@#$"}},
+ true, true, true, {}));
+
+ ASSERT_TRUE(cap.parse("allow command abc with arg regex \"[*\"", nullptr));
+ ASSERT_FALSE(cap.is_capable(nullptr, name, "", "", "abc", {{"arg", ""}}, true,
+ true, true, {}));
+}
+
+TEST(MgrCap, Module) {
+ MgrCap cap;
+ ASSERT_FALSE(cap.is_allow_all());
+ ASSERT_TRUE(cap.parse("allow module abc r, allow module bcd w", nullptr));
+
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, true, false,
+ {}));
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false, false,
+ {}));
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "bcd", "", {}, true, true, false,
+ {}));
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "bcd", "", {}, false, true, false,
+ {}));
+}
+
+TEST(MgrCap, Profile) {
+ MgrCap cap;
+ ASSERT_FALSE(cap.is_allow_all());
+
+ ASSERT_FALSE(cap.parse("profile unknown"));
+ ASSERT_FALSE(cap.parse("profile rbd invalid-key=value"));
+
+ ASSERT_TRUE(cap.parse("profile rbd", nullptr));
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false,
+ false, {}));
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
+ true, false, {}));
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
+ false, false, {}));
+
+ ASSERT_TRUE(cap.parse("profile rbd pool=abc namespace prefix def", nullptr));
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {},
+ true, true, false, {}));
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "",
+ {{"pool", "abc"}},
+ true, true, false, {}));
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "",
+ {{"pool", "abc"}, {"namespace", "defghi"}},
+ true, true, false, {}));
+
+ ASSERT_TRUE(cap.parse("profile rbd-read-only", nullptr));
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false,
+ false, {}));
+ ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
+ true, false, {}));
+ ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true,
+ false, false, {}));
+}
diff --git a/src/test/mgr/test_ttlcache.cc b/src/test/mgr/test_ttlcache.cc
new file mode 100644
index 000000000..a1ee0a862
--- /dev/null
+++ b/src/test/mgr/test_ttlcache.cc
@@ -0,0 +1,70 @@
+#include <iostream>
+
+#include "mgr/TTLCache.h"
+#include "gtest/gtest.h"
+
+using namespace std;
+
+TEST(TTLCache, Get) {
+ TTLCache<string, int> c{100};
+ c.insert("foo", 1);
+ int foo = c.get("foo");
+ ASSERT_EQ(foo, 1);
+}
+
+TEST(TTLCache, Erase) {
+ TTLCache<string, int> c{100};
+ c.insert("foo", 1);
+ int foo = c.get("foo");
+ ASSERT_EQ(foo, 1);
+ c.erase("foo");
+ try{
+ foo = c.get("foo");
+ FAIL();
+ } catch (std::out_of_range& e) {
+ SUCCEED();
+ }
+}
+
+TEST(TTLCache, Clear) {
+ TTLCache<string, int> c{100};
+ c.insert("foo", 1);
+ c.insert("foo2", 2);
+ c.clear();
+ ASSERT_FALSE(c.size());
+}
+
+TEST(TTLCache, NoTTL) {
+ TTLCache<string, int> c{100};
+ c.insert("foo", 1);
+ int foo = c.get("foo");
+ ASSERT_EQ(foo, 1);
+ c.set_ttl(0);
+ c.insert("foo2", 2);
+ try{
+ foo = c.get("foo2");
+ FAIL();
+ } catch (std::out_of_range& e) {
+ SUCCEED();
+ }
+}
+
+TEST(TTLCache, SizeLimit) {
+ TTLCache<string, int> c{100, 2};
+ c.insert("foo", 1);
+ c.insert("foo2", 2);
+ c.insert("foo3", 3);
+ ASSERT_EQ(c.size(), 2);
+}
+
+TEST(TTLCache, HitRatio) {
+ TTLCache<string, int> c{100};
+ c.insert("foo", 1);
+ c.insert("foo2", 2);
+ c.insert("foo3", 3);
+ c.get("foo2");
+ c.get("foo3");
+ std::pair<uint64_t, uint64_t> hit_miss_ratio = c.get_hit_miss_ratio();
+ ASSERT_EQ(std::get<1>(hit_miss_ratio), 3);
+ ASSERT_EQ(std::get<0>(hit_miss_ratio), 2);
+}