Skip to content

Commit

Permalink
Fixes #25841: Create an instance id on each root server
Browse files Browse the repository at this point in the history
  • Loading branch information
clarktsiory committed Nov 18, 2024
1 parent 28b911b commit cbb201d
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3214,13 +3214,16 @@ object RudderConfigInit {
lazy val mainCampaignService = new MainCampaignService(campaignEventRepo, campaignRepo, uuidGen, 1, 1)
lazy val jsonReportsAnalyzer = JSONReportsAnalyser(reportsRepository, propertyRepository)

lazy val instanceUuidPath = root / "opt" / "rudder" / "etc" / "instance-id"

/*
* *************************************************
* Bootstrap check actions
* **************************************************
*/

lazy val allBootstrapChecks = new SequentialImmediateBootStrapChecks(
new CreateInstanceUuid(instanceUuidPath, stringUuidGenerator),
new CheckConnections(dataSourceProvider, rwLdap),
new CheckTableScore(doobie),
new CheckTableUsers(doobie),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
*************************************************************************************
* Copyright 2024 Normation SAS
*************************************************************************************
*
* This file is part of Rudder.
*
* Rudder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In accordance with the terms of section 7 (7. Additional Terms.) of
* the GNU General Public License version 3, the copyright holders add
* the following Additional permissions:
* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
* Public License version 3, when you create a Related Module, this
* Related Module is not considered as a part of the work and may be
* distributed under the license agreement of your choice.
* A "Related Module" means a set of sources files including their
* documentation that, without modification of the Source Code, enables
* supplementary functions or services in addition to those offered by
* the Software.
*
* Rudder 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Rudder. If not, see <http://www.gnu.org/licenses/>.
*
*************************************************************************************
*/

package bootstrap.liftweb.checks.action

import better.files.File
import bootstrap.liftweb.BootstrapChecks
import bootstrap.liftweb.BootstrapLogger
import com.normation.errors.IOResult
import com.normation.errors.PureResult
import com.normation.utils.StringUuidGenerator
import com.normation.zio.UnsafeRun
import java.util.UUID
import zio.ZIO

class CreateInstanceUuid(file: File, uuidGen: StringUuidGenerator) extends BootstrapChecks {

private val filePath = file.pathAsString

override def description: String = "Check if server has instance UUID, if not, create it"

override def checks(): Unit = {
(for {
content <- getOrCreateFile()
_ <- ZIO.unless(isValidUUID(content)) {
writeFile(uuidGen.newUuid)
}
} yield ())
.chainError(s"An error occured when creating instance UUID in ${filePath} for server")
.tapError(err => BootstrapLogger.error(err.fullMsg))
.runNow
}

private def getOrCreateFile(): IOResult[String] = {
IOResult.attempt("Could not create or access file")(file.createIfNotExists().contentAsString)
}

private def writeFile(uuid: String): IOResult[Unit] = {
IOResult.attempt("Could not write to file")(file.write(uuid))
}

/**
* Valid UUID is a parsable one
*/
private def isValidUUID(content: String): Boolean = {
PureResult.attempt(UUID.fromString(content)).isRight
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package bootstrap.liftweb.checks.action

import better.files.File
import com.normation.utils.StringUuidGenerator
import com.normation.utils.StringUuidGeneratorImpl
import org.specs2.mutable.Specification

class TestCreateInstanceUuid extends Specification {

"When creating instance ID, we" should {
val uuid: String = "00000000-0000-0000-0000-000000000000"
val uuidGen = new StringUuidGenerator {
val newUuid: String = uuid
}

"initialize file if it does not exist" in File.temporaryDirectory("rudder-test-instance-id-") { tmpDir =>
val file = tmpDir / "instance-id"
val check = new CreateInstanceUuid(file, uuidGen)
file.exists must beFalse
check.checks()

file.contentAsString must beEqualTo(uuid)
}

"renew ID when file content is not an UUID" in File.temporaryDirectory("rudder-test-instance-id-") { tmpDir =>
val file = tmpDir / "instance-id"
file.write("root-id")
val check = new CreateInstanceUuid(file, uuidGen)
check.checks()

file.contentAsString must beEqualTo(uuid)
}

"check for existing ID and not overwrite it" in File.temporaryDirectory("rudder-test-instance-id-") { tmpDir =>
val file = tmpDir / "instance-id"
val randomUuidGen = new StringUuidGeneratorImpl()
file.write(uuid)
val check = new CreateInstanceUuid(file, randomUuidGen)
check.checks()

file.contentAsString must beEqualTo(uuid)
}
}

}

0 comments on commit cbb201d

Please sign in to comment.