mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Add tools for remigration and domain level raising (#2481)
This commit is contained in:
parent
a1fbde9f2f
commit
9050188b29
|
@ -173,6 +173,14 @@ pub enum Oauth2ClaimMapJoin {
|
||||||
Array,
|
Array,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct DomainInfo {
|
||||||
|
pub name: String,
|
||||||
|
pub displayname: String,
|
||||||
|
pub uuid: Uuid,
|
||||||
|
pub level: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_fstype_deser() {
|
fn test_fstype_deser() {
|
||||||
assert_eq!(FsType::try_from("zfs"), Ok(FsType::Zfs));
|
assert_eq!(FsType::try_from("zfs"), Ok(FsType::Zfs));
|
||||||
|
|
|
@ -296,7 +296,11 @@ pub enum OperationError {
|
||||||
VS0001IncomingReplSshPublicKey,
|
VS0001IncomingReplSshPublicKey,
|
||||||
// Value Errors
|
// Value Errors
|
||||||
VL0001ValueSshPublicKeyString,
|
VL0001ValueSshPublicKeyString,
|
||||||
|
// SCIM
|
||||||
SC0001IncomingSshPublicKey,
|
SC0001IncomingSshPublicKey,
|
||||||
|
// Migration
|
||||||
|
MG0001InvalidReMigrationLevel,
|
||||||
|
MG0002RaiseDomainLevelExceedsMaximum,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for OperationError {
|
impl PartialEq for OperationError {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
ARG BASE_IMAGE=opensuse/tumbleweed:latest
|
ARG BASE_IMAGE=opensuse/tumbleweed:latest
|
||||||
|
# ARG BASE_IMAGE=opensuse/leap:15.5
|
||||||
|
|
||||||
# FROM ${BASE_IMAGE} as repos
|
# FROM ${BASE_IMAGE} as repos
|
||||||
FROM ${BASE_IMAGE}
|
FROM ${BASE_IMAGE}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# Build the main Kanidmd server
|
# Build the main Kanidmd server
|
||||||
ARG BASE_IMAGE=opensuse/tumbleweed:latest
|
ARG BASE_IMAGE=opensuse/tumbleweed:latest
|
||||||
|
# ARG BASE_IMAGE=opensuse/leap:15.5
|
||||||
|
|
||||||
FROM ${BASE_IMAGE} AS repos
|
FROM ${BASE_IMAGE} AS repos
|
||||||
ADD scripts/zypper_fixing.sh /zypper_fixing.sh
|
ADD scripts/zypper_fixing.sh /zypper_fixing.sh
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::{iter, sync::Arc};
|
use std::{iter, sync::Arc};
|
||||||
|
|
||||||
|
use kanidm_proto::internal::DomainInfo as ProtoDomainInfo;
|
||||||
use kanidm_proto::internal::ImageValue;
|
use kanidm_proto::internal::ImageValue;
|
||||||
use kanidm_proto::internal::Oauth2ClaimMapJoin as ProtoOauth2ClaimMapJoin;
|
use kanidm_proto::internal::Oauth2ClaimMapJoin as ProtoOauth2ClaimMapJoin;
|
||||||
use kanidm_proto::v1::{
|
use kanidm_proto::v1::{
|
||||||
|
@ -1820,4 +1821,57 @@ impl QueryServerWriteV1 {
|
||||||
|
|
||||||
idms_prox_write.commit().map(|()| pw)
|
idms_prox_write.commit().map(|()| pw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(
|
||||||
|
level = "info",
|
||||||
|
skip_all,
|
||||||
|
fields(uuid = ?eventid)
|
||||||
|
)]
|
||||||
|
pub(crate) async fn handle_domain_show(
|
||||||
|
&self,
|
||||||
|
eventid: Uuid,
|
||||||
|
) -> Result<ProtoDomainInfo, OperationError> {
|
||||||
|
trace!("Begin domain show event");
|
||||||
|
let ct = duration_from_epoch_now();
|
||||||
|
let mut idms_prox_write = self.idms.proxy_write(ct).await;
|
||||||
|
|
||||||
|
let domain_info = idms_prox_write.qs_write.domain_info()?;
|
||||||
|
|
||||||
|
idms_prox_write.commit().map(|()| domain_info)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(
|
||||||
|
level = "info",
|
||||||
|
skip_all,
|
||||||
|
fields(uuid = ?eventid)
|
||||||
|
)]
|
||||||
|
pub(crate) async fn handle_domain_raise(&self, eventid: Uuid) -> Result<u32, OperationError> {
|
||||||
|
trace!("Begin domain raise event");
|
||||||
|
let ct = duration_from_epoch_now();
|
||||||
|
let mut idms_prox_write = self.idms.proxy_write(ct).await;
|
||||||
|
|
||||||
|
idms_prox_write.qs_write.domain_raise(DOMAIN_MAX_LEVEL)?;
|
||||||
|
|
||||||
|
idms_prox_write.commit().map(|()| DOMAIN_MAX_LEVEL)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(
|
||||||
|
level = "info",
|
||||||
|
skip_all,
|
||||||
|
fields(uuid = ?eventid)
|
||||||
|
)]
|
||||||
|
pub(crate) async fn handle_domain_remigrate(
|
||||||
|
&self,
|
||||||
|
level: Option<u32>,
|
||||||
|
eventid: Uuid,
|
||||||
|
) -> Result<(), OperationError> {
|
||||||
|
let level = level.unwrap_or(DOMAIN_MIN_REMIGRATION_LEVEL);
|
||||||
|
trace!(%level, "Begin domain remigrate event");
|
||||||
|
let ct = duration_from_epoch_now();
|
||||||
|
let mut idms_prox_write = self.idms.proxy_write(ct).await;
|
||||||
|
|
||||||
|
idms_prox_write.qs_write.domain_remigrate(level)?;
|
||||||
|
|
||||||
|
idms_prox_write.commit()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,25 @@ use tokio_util::codec::{Decoder, Encoder, Framed};
|
||||||
use tracing::{span, Instrument, Level};
|
use tracing::{span, Instrument, Level};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub use kanidm_proto::internal::DomainInfo as ProtoDomainInfo;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub enum AdminTaskRequest {
|
pub enum AdminTaskRequest {
|
||||||
RecoverAccount { name: String },
|
RecoverAccount { name: String },
|
||||||
ShowReplicationCertificate,
|
ShowReplicationCertificate,
|
||||||
RenewReplicationCertificate,
|
RenewReplicationCertificate,
|
||||||
RefreshReplicationConsumer,
|
RefreshReplicationConsumer,
|
||||||
|
DomainShow,
|
||||||
|
DomainRaise,
|
||||||
|
DomainRemigrate { level: Option<u32> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub enum AdminTaskResponse {
|
pub enum AdminTaskResponse {
|
||||||
RecoverAccount { password: String },
|
RecoverAccount { password: String },
|
||||||
ShowReplicationCertificate { cert: String },
|
ShowReplicationCertificate { cert: String },
|
||||||
|
DomainRaise { level: u32 },
|
||||||
|
DomainShow { domain_info: ProtoDomainInfo },
|
||||||
Success,
|
Success,
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
@ -315,6 +322,30 @@ async fn handle_client(
|
||||||
AdminTaskResponse::Error
|
AdminTaskResponse::Error
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
AdminTaskRequest::DomainShow => match server.handle_domain_show(eventid).await {
|
||||||
|
Ok(domain_info) => AdminTaskResponse::DomainShow { domain_info },
|
||||||
|
Err(e) => {
|
||||||
|
error!(err = ?e, "error during domain show");
|
||||||
|
AdminTaskResponse::Error
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AdminTaskRequest::DomainRaise => match server.handle_domain_raise(eventid).await {
|
||||||
|
Ok(level) => AdminTaskResponse::DomainRaise { level },
|
||||||
|
Err(e) => {
|
||||||
|
error!(err = ?e, "error during domain raise");
|
||||||
|
AdminTaskResponse::Error
|
||||||
|
}
|
||||||
|
},
|
||||||
|
AdminTaskRequest::DomainRemigrate { level } => {
|
||||||
|
match server.handle_domain_remigrate(level, eventid).await {
|
||||||
|
Ok(()) => AdminTaskResponse::Success,
|
||||||
|
Err(e) => {
|
||||||
|
error!(err = ?e, "error during domain remigrate");
|
||||||
|
AdminTaskResponse::Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.instrument(nspan)
|
.instrument(nspan)
|
||||||
|
|
|
@ -30,7 +30,7 @@ use clap::{Args, Parser, Subcommand};
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
#[cfg(not(target_family = "windows"))] // not needed for windows builds
|
#[cfg(not(target_family = "windows"))] // not needed for windows builds
|
||||||
use kanidm_utils_users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
|
use kanidm_utils_users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
|
||||||
use kanidmd_core::admin::{AdminTaskRequest, AdminTaskResponse, ClientCodec};
|
use kanidmd_core::admin::{AdminTaskRequest, AdminTaskResponse, ClientCodec, ProtoDomainInfo};
|
||||||
use kanidmd_core::config::{Configuration, ServerConfig};
|
use kanidmd_core::config::{Configuration, ServerConfig};
|
||||||
use kanidmd_core::{
|
use kanidmd_core::{
|
||||||
backup_server_core, cert_generate_core, create_server_core, dbscan_get_id2entry_core,
|
backup_server_core, cert_generate_core, create_server_core, dbscan_get_id2entry_core,
|
||||||
|
@ -89,8 +89,17 @@ impl KanidmdOpt {
|
||||||
commands: DbScanOpt::GetId2Entry(dopt),
|
commands: DbScanOpt::GetId2Entry(dopt),
|
||||||
} => &dopt.commonopts,
|
} => &dopt.commonopts,
|
||||||
KanidmdOpt::DomainSettings {
|
KanidmdOpt::DomainSettings {
|
||||||
commands: DomainSettingsCmds::DomainChange(sopt),
|
commands: DomainSettingsCmds::Show { commonopts },
|
||||||
} => sopt,
|
}
|
||||||
|
| KanidmdOpt::DomainSettings {
|
||||||
|
commands: DomainSettingsCmds::Change { commonopts },
|
||||||
|
}
|
||||||
|
| KanidmdOpt::DomainSettings {
|
||||||
|
commands: DomainSettingsCmds::Raise { commonopts },
|
||||||
|
}
|
||||||
|
| KanidmdOpt::DomainSettings {
|
||||||
|
commands: DomainSettingsCmds::Remigrate { commonopts, .. },
|
||||||
|
} => commonopts,
|
||||||
KanidmdOpt::Database {
|
KanidmdOpt::Database {
|
||||||
commands: DbCommands::Verify(sopt),
|
commands: DbCommands::Verify(sopt),
|
||||||
}
|
}
|
||||||
|
@ -161,6 +170,36 @@ async fn submit_admin_req(path: &str, req: AdminTaskRequest, output_mode: Consol
|
||||||
info!(certificate = ?cert)
|
info!(certificate = ?cert)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Some(Ok(AdminTaskResponse::DomainRaise { level })) => match output_mode {
|
||||||
|
ConsoleOutputMode::JSON => {
|
||||||
|
eprintln!("{{\"success\":\"{}\"}}", level)
|
||||||
|
}
|
||||||
|
ConsoleOutputMode::Text => {
|
||||||
|
info!("success - raised domain level to {}", level)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(Ok(AdminTaskResponse::DomainShow { domain_info })) => match output_mode {
|
||||||
|
ConsoleOutputMode::JSON => {
|
||||||
|
let json_output = serde_json::json!({
|
||||||
|
"domain_info": domain_info
|
||||||
|
});
|
||||||
|
println!("{}", json_output);
|
||||||
|
}
|
||||||
|
ConsoleOutputMode::Text => {
|
||||||
|
let ProtoDomainInfo {
|
||||||
|
name,
|
||||||
|
displayname,
|
||||||
|
uuid,
|
||||||
|
level,
|
||||||
|
} = domain_info;
|
||||||
|
|
||||||
|
info!("domain_name : {}", name);
|
||||||
|
info!("domain_display: {}", displayname);
|
||||||
|
info!("domain_uuid : {}", uuid);
|
||||||
|
info!("domain_level : {}", level);
|
||||||
|
}
|
||||||
|
},
|
||||||
Some(Ok(AdminTaskResponse::Success)) => match output_mode {
|
Some(Ok(AdminTaskResponse::Success)) => match output_mode {
|
||||||
ConsoleOutputMode::JSON => {
|
ConsoleOutputMode::JSON => {
|
||||||
eprintln!("\"success\"")
|
eprintln!("\"success\"")
|
||||||
|
@ -717,11 +756,49 @@ async fn kanidm_main() -> ExitCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
KanidmdOpt::DomainSettings {
|
KanidmdOpt::DomainSettings {
|
||||||
commands: DomainSettingsCmds::DomainChange(_dopt),
|
commands: DomainSettingsCmds::Change { .. },
|
||||||
} => {
|
} => {
|
||||||
info!("Running in domain name change mode ... this may take a long time ...");
|
info!("Running in domain name change mode ... this may take a long time ...");
|
||||||
domain_rename_core(&config).await;
|
domain_rename_core(&config).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KanidmdOpt::DomainSettings {
|
||||||
|
commands: DomainSettingsCmds::Show { commonopts },
|
||||||
|
} => {
|
||||||
|
info!("Running domain show ...");
|
||||||
|
let output_mode: ConsoleOutputMode = commonopts.output_mode.to_owned().into();
|
||||||
|
submit_admin_req(
|
||||||
|
config.adminbindpath.as_str(),
|
||||||
|
AdminTaskRequest::DomainShow,
|
||||||
|
output_mode,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
KanidmdOpt::DomainSettings {
|
||||||
|
commands: DomainSettingsCmds::Raise { commonopts },
|
||||||
|
} => {
|
||||||
|
info!("Running domain raise ...");
|
||||||
|
let output_mode: ConsoleOutputMode = commonopts.output_mode.to_owned().into();
|
||||||
|
submit_admin_req(
|
||||||
|
config.adminbindpath.as_str(),
|
||||||
|
AdminTaskRequest::DomainRaise,
|
||||||
|
output_mode,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
KanidmdOpt::DomainSettings {
|
||||||
|
commands: DomainSettingsCmds::Remigrate { commonopts, level },
|
||||||
|
} => {
|
||||||
|
info!("Running domain remigrate ...");
|
||||||
|
let output_mode: ConsoleOutputMode = commonopts.output_mode.to_owned().into();
|
||||||
|
submit_admin_req(
|
||||||
|
config.adminbindpath.as_str(),
|
||||||
|
AdminTaskRequest::DomainRemigrate { level: *level },
|
||||||
|
output_mode,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
KanidmdOpt::Database {
|
KanidmdOpt::Database {
|
||||||
commands: DbCommands::Vacuum(_copt),
|
commands: DbCommands::Vacuum(_copt),
|
||||||
} => {
|
} => {
|
||||||
|
|
|
@ -28,9 +28,32 @@ struct RestoreOpt {
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
enum DomainSettingsCmds {
|
enum DomainSettingsCmds {
|
||||||
|
#[clap(name = "show")]
|
||||||
|
/// Show the current domain
|
||||||
|
Show {
|
||||||
|
#[clap(flatten)]
|
||||||
|
commonopts: CommonOpt,
|
||||||
|
},
|
||||||
#[clap(name = "rename")]
|
#[clap(name = "rename")]
|
||||||
/// Change the IDM domain name
|
/// Change the IDM domain name based on the values in the configuration
|
||||||
DomainChange(CommonOpt),
|
Change {
|
||||||
|
#[clap(flatten)]
|
||||||
|
commonopts: CommonOpt,
|
||||||
|
},
|
||||||
|
#[clap(name = "raise")]
|
||||||
|
/// Raise the functional level of this domain to the maximum available.
|
||||||
|
Raise {
|
||||||
|
#[clap(flatten)]
|
||||||
|
commonopts: CommonOpt,
|
||||||
|
},
|
||||||
|
#[clap(name = "remigrate")]
|
||||||
|
/// Rerun migrations of this domains database, optionally nominating the level
|
||||||
|
/// to start from.
|
||||||
|
Remigrate {
|
||||||
|
#[clap(flatten)]
|
||||||
|
commonopts: CommonOpt,
|
||||||
|
level: Option<u32>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
|
|
|
@ -49,6 +49,8 @@ pub const DOMAIN_LEVEL_2: DomainVersion = 2;
|
||||||
pub const DOMAIN_LEVEL_3: DomainVersion = 3;
|
pub const DOMAIN_LEVEL_3: DomainVersion = 3;
|
||||||
pub const DOMAIN_LEVEL_4: DomainVersion = 4;
|
pub const DOMAIN_LEVEL_4: DomainVersion = 4;
|
||||||
pub const DOMAIN_LEVEL_5: DomainVersion = 5;
|
pub const DOMAIN_LEVEL_5: DomainVersion = 5;
|
||||||
|
// The minimum level that we can re-migrate from
|
||||||
|
pub const DOMAIN_MIN_REMIGRATION_LEVEL: DomainVersion = DOMAIN_LEVEL_2;
|
||||||
// The minimum supported domain functional level
|
// The minimum supported domain functional level
|
||||||
pub const DOMAIN_MIN_LEVEL: DomainVersion = DOMAIN_LEVEL_5;
|
pub const DOMAIN_MIN_LEVEL: DomainVersion = DOMAIN_LEVEL_5;
|
||||||
// The target supported domain functional level
|
// The target supported domain functional level
|
||||||
|
|
|
@ -781,10 +781,10 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
self.internal_modify(&filter, &modlist)?;
|
self.internal_modify(&filter, &modlist)?;
|
||||||
|
|
||||||
// Now move all oauth2 rs name.
|
// Now move all oauth2 rs name.
|
||||||
let filter = filter!(f_eq(
|
let filter = filter!(f_and!([
|
||||||
Attribute::Class,
|
f_eq(Attribute::Class, EntryClass::OAuth2ResourceServer.into()),
|
||||||
EntryClass::OAuth2ResourceServer.into()
|
f_pres(Attribute::OAuth2RsName),
|
||||||
));
|
]));
|
||||||
|
|
||||||
let pre_candidates = self.internal_search(filter).map_err(|err| {
|
let pre_candidates = self.internal_search(filter).map_err(|err| {
|
||||||
admin_error!(?err, "migrate_domain_4_to_5 internal search failure");
|
admin_error!(?err, "migrate_domain_4_to_5 internal search failure");
|
||||||
|
|
|
@ -11,6 +11,7 @@ use std::collections::BTreeSet;
|
||||||
use tokio::sync::{Semaphore, SemaphorePermit};
|
use tokio::sync::{Semaphore, SemaphorePermit};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
|
use kanidm_proto::internal::DomainInfo as ProtoDomainInfo;
|
||||||
use kanidm_proto::v1::{ConsistencyError, UiHint};
|
use kanidm_proto::v1::{ConsistencyError, UiHint};
|
||||||
|
|
||||||
use crate::be::{Backend, BackendReadTransaction, BackendTransaction, BackendWriteTransaction};
|
use crate::be::{Backend, BackendReadTransaction, BackendTransaction, BackendWriteTransaction};
|
||||||
|
@ -1385,6 +1386,48 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
&mut self.dyngroup_cache
|
&mut self.dyngroup_cache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn domain_info(&mut self) -> Result<ProtoDomainInfo, OperationError> {
|
||||||
|
let d_info = &self.d_info;
|
||||||
|
|
||||||
|
Ok(ProtoDomainInfo {
|
||||||
|
name: d_info.d_name.clone(),
|
||||||
|
displayname: d_info.d_display.clone(),
|
||||||
|
uuid: d_info.d_uuid,
|
||||||
|
level: d_info.d_vers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn domain_raise(&mut self, level: u32) -> Result<(), OperationError> {
|
||||||
|
if level > DOMAIN_MAX_LEVEL {
|
||||||
|
return Err(OperationError::MG0002RaiseDomainLevelExceedsMaximum);
|
||||||
|
}
|
||||||
|
|
||||||
|
let modl = ModifyList::new_purge_and_set(Attribute::Version, Value::Uint32(level));
|
||||||
|
let udi = PVUUID_DOMAIN_INFO.clone();
|
||||||
|
let filt = filter_all!(f_eq(Attribute::Uuid, udi));
|
||||||
|
self.internal_modify(&filt, &modl)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn domain_remigrate(&mut self, level: u32) -> Result<(), OperationError> {
|
||||||
|
let mut_d_info = self.d_info.get_mut();
|
||||||
|
|
||||||
|
if level > mut_d_info.d_vers {
|
||||||
|
// Nothing to do.
|
||||||
|
return Ok(());
|
||||||
|
} else if level < DOMAIN_MIN_REMIGRATION_LEVEL {
|
||||||
|
return Err(OperationError::MG0001InvalidReMigrationLevel);
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"Prepare to re-migrate from {} -> {}",
|
||||||
|
level, mut_d_info.d_vers
|
||||||
|
);
|
||||||
|
mut_d_info.d_vers = level;
|
||||||
|
self.changed_domain = true;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip_all)]
|
#[instrument(level = "debug", skip_all)]
|
||||||
pub(crate) fn reload_schema(&mut self) -> Result<(), OperationError> {
|
pub(crate) fn reload_schema(&mut self) -> Result<(), OperationError> {
|
||||||
// supply entries to the writable schema to reload from.
|
// supply entries to the writable schema to reload from.
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
# This builds the kanidm CLI tools
|
# This builds the kanidm CLI tools
|
||||||
ARG BASE_IMAGE=opensuse/tumbleweed:latest
|
ARG BASE_IMAGE=opensuse/tumbleweed:latest
|
||||||
|
# ARG BASE_IMAGE=opensuse/leap:15.5
|
||||||
|
|
||||||
FROM ${BASE_IMAGE} AS repos
|
FROM ${BASE_IMAGE} AS repos
|
||||||
ADD ../scripts/zypper_fixing.sh /zypper_fixing.sh
|
ADD ../scripts/zypper_fixing.sh /zypper_fixing.sh
|
||||||
RUN --mount=type=cache,id=zypp,target=/var/cache/zypp /zypper_fixing.sh
|
RUN --mount=type=cache,id=zypp,target=/var/cache/zypp /zypper_fixing.sh
|
||||||
|
|
Loading…
Reference in a new issue