Implement more of manifestutil

This commit is contained in:
Greg Neagle
2025-04-14 16:00:21 -07:00
parent 2dbc418f7d
commit 834f272dc0
6 changed files with 138 additions and 19 deletions
+16 -9
View File
@@ -22,13 +22,13 @@ import ArgumentParser
import Foundation
/// Returns a list of available catalogs
func getCatalogNames(repo: Repo) throws -> [String] {
func getCatalogNames(repo: Repo) -> [String]? {
do {
let catalogNames = try repo.list("catalogs")
return catalogNames.sorted()
} catch {
printStderr("Could not retrieve catalogs: \(error.localizedDescription)")
throw ExitCode(-1)
return nil
}
}
@@ -39,9 +39,11 @@ extension ManifestUtil {
abstract: "Lists available catalogs in Munki repo.")
func run() throws {
let repo = try connectToRepo()
let catalogNames = try getCatalogNames(repo: repo)
print(catalogNames.joined(separator: "\n"))
if let repo = try? connectToRepo(),
let catalogNames = getCatalogNames(repo: repo)
{
print(catalogNames.joined(separator: "\n"))
}
}
}
}
@@ -49,7 +51,9 @@ extension ManifestUtil {
/// Returns a list of unique installer item (pkg) names from the given list of catalogs
func getInstallerItemNames(repo: Repo, catalogs: [String]) throws -> [String] {
var itemList = [String]()
let catalogNames = try getCatalogNames(repo: repo)
guard let catalogNames = getCatalogNames(repo: repo) else {
return itemList
}
for catalogName in catalogNames {
if catalogs.contains(catalogName) {
do {
@@ -92,11 +96,14 @@ extension ManifestUtil {
}
func run() throws {
let repo = try connectToRepo()
let avaliableCatalogs = try getCatalogNames(repo: repo)
guard let repo = try? connectToRepo(),
let availableCatalogs = getCatalogNames(repo: repo)
else {
return
}
for catalogName in catalogNames {
if !avaliableCatalogs.contains(catalogName) {
if !availableCatalogs.contains(catalogName) {
printStderr("Catalog '\(catalogName)' does not exist.")
throw ExitCode(-1)
}
@@ -107,7 +107,7 @@ extension ManifestUtil {
var manifestName: String
func run() throws {
let repo = try connectToRepo()
guard let repo = try? connectToRepo() else { return }
if var manifest = getManifest(repo: repo, name: manifestName) {
if expand {
manifest = expandIncludedManifests(repo: repo, manifest: manifest)
@@ -141,7 +141,7 @@ extension ManifestUtil {
var manifestName: String
func run() throws {
let repo = try connectToRepo()
guard let repo = try? connectToRepo() else { return }
if var manifest = getManifest(repo: repo, name: manifestName) {
manifest = expandIncludedManifests(repo: repo, manifest: manifest)
if xml {
@@ -43,8 +43,9 @@ extension ManifestUtil {
var globString: String = ""
func run() throws {
let repo = try connectToRepo()
guard let manifestNames = getManifestNames(repo: repo) else {
guard let repo = try? connectToRepo(),
let manifestNames = getManifestNames(repo: repo)
else {
return
}
if globString.isEmpty {
@@ -0,0 +1,111 @@
//
// MUmanifestEditing.swift
// manifestutil
//
// Created by Greg Neagle on 4/14/25.
//
// Copyright 2024-2025 Greg Neagle.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import ArgumentParser
import Foundation
/// Adds a catalog to a manifest.
func addCatalog(repo: Repo, manifestName: String, catalogName: String) -> Bool {
let availableCatalogs = getCatalogNames(repo: repo) ?? []
if !availableCatalogs.contains(catalogName) {
printStderr("Unknown catalog name: \(catalogName)")
return false
}
guard var manifest = getManifest(repo: repo, name: manifestName) else {
return false
}
var catalogs = manifest["catalogs"] as? [String] ?? []
if catalogs.contains(catalogName) {
printStderr("Catalog \(catalogName) is already in manifest \(manifestName)")
return false
}
// put it at the front of the catalog list as that is usually
// what is wanted...
catalogs.insert(catalogName, at: 0)
manifest["catalogs"] = catalogs
if saveManifest(repo: repo, manifest: manifest, name: manifestName, overwrite: true) {
print("Added \(catalogName) to catalogs of manifest \(manifestName).")
return true
}
return false
}
func removeCatalog(repo: Repo, manifestName: String, catalogName: String) -> Bool {
guard var manifest = getManifest(repo: repo, name: manifestName) else {
return false
}
var catalogs = manifest["catalogs"] as? [String] ?? []
if let index = catalogs.firstIndex(of: catalogName) {
catalogs.remove(at: index)
manifest["catalogs"] = catalogs
if saveManifest(repo: repo, manifest: manifest, name: manifestName, overwrite: true) {
print("Removed \(catalogName) from catalogs of manifest \(manifestName).")
return true
}
}
printStderr("Catalog \(catalogName) is not in manifest \(manifestName).")
return false
}
/// Add a catalog to a manifest
extension ManifestUtil {
struct AddCatalog: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "Adds a catalog to a manifest")
@Option(help: ArgumentHelp("Name of manifest",
valueName: "manifest-name"))
var manifest: String
@Argument(help: ArgumentHelp(
"Name of the catalog to be added",
valueName: "catalog-name"
))
var catalogName: String
func run() throws {
guard let repo = try? connectToRepo() else { return }
_ = addCatalog(repo: repo, manifestName: manifest, catalogName: catalogName)
}
}
}
/// Remove a catalog from a manifest
extension ManifestUtil {
struct RemoveCatalog: ParsableCommand {
static var configuration = CommandConfiguration(
abstract: "Removes a catalog from a manifest")
@Option(help: ArgumentHelp("Name of manifest",
valueName: "manifest-name"))
var manifest: String
@Argument(help: ArgumentHelp(
"Name of the catalog to be removed",
valueName: "catalog-name"
))
var catalogName: String
func run() throws {
guard let repo = try? connectToRepo() else { return }
_ = removeCatalog(repo: repo, manifestName: manifest, catalogName: catalogName)
}
}
}
@@ -107,7 +107,7 @@ extension ManifestUtil {
var manifestName: String
func run() throws {
let repo = try connectToRepo()
guard let repo = try? connectToRepo() else { return }
_ = newManifest(repo: repo, name: manifestName)
}
}
@@ -132,7 +132,7 @@ extension ManifestUtil {
var destinationName: String
func run() throws {
let repo = try connectToRepo()
guard let repo = try? connectToRepo() else { return }
_ = copyOrRenameManifest(
repo: repo,
sourceName: sourceName,
@@ -161,7 +161,7 @@ extension ManifestUtil {
var destinationName: String
func run() throws {
let repo = try connectToRepo()
guard let repo = try? connectToRepo() else { return }
_ = copyOrRenameManifest(
repo: repo,
sourceName: sourceName,
@@ -185,7 +185,7 @@ extension ManifestUtil {
var manifestName: String
func run() throws {
let repo = try connectToRepo()
guard let repo = try? connectToRepo() else { return }
_ = deleteManifest(repo: repo, name: manifestName)
}
}
@@ -48,11 +48,11 @@ struct ManifestUtil: AsyncParsableCommand {
abstract: "A utility for working with Munki manifests.",
subcommands: [
// AddPkg.self,
// AddCatalog.self,
AddCatalog.self,
// AddIncludedManifest.self,
// RemovePkg.self,
// MoveInstallToUninstall.self,
// RemoveCatalog.self,
RemoveCatalog.self,
// RemoveIncludedManifest.self,
ListCatalogs.self,
ListCatalogItems.self,