diff --git a/cmd/database.go b/cmd/database.go new file mode 100644 index 00000000..953906da --- /dev/null +++ b/cmd/database.go @@ -0,0 +1,37 @@ +// Copyright © 2019 Ettore Di Giacinto +// Daniele Rondina +// +// This program 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 2 of the License, 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package cmd + +import ( + . "github.com/mudler/luet/cmd/database" + + "github.com/spf13/cobra" +) + +var databaseGroupCmd = &cobra.Command{ + Use: "database [command] [OPTIONS]", + Short: "Manage system database (dangerous commands ahead!)", +} + +func init() { + RootCmd.AddCommand(databaseGroupCmd) + + databaseGroupCmd.AddCommand( + NewDatabaseCreateCommand(), + NewDatabaseRemoveCommand(), + ) +} diff --git a/cmd/database/create.go b/cmd/database/create.go new file mode 100644 index 00000000..75dc9121 --- /dev/null +++ b/cmd/database/create.go @@ -0,0 +1,81 @@ +// Copyright © 2020 Ettore Di Giacinto +// +// This program 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 2 of the License, 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package cmd_database + +import ( + "io/ioutil" + "path/filepath" + + "github.com/mudler/luet/pkg/compiler" + . "github.com/mudler/luet/pkg/logger" + pkg "github.com/mudler/luet/pkg/package" + + . "github.com/mudler/luet/pkg/config" + + "github.com/spf13/cobra" +) + +func NewDatabaseCreateCommand() *cobra.Command { + var ans = &cobra.Command{ + Use: "create ", + Short: "Insert a package in the system DB", + Args: cobra.OnlyValidArgs, + PreRun: func(cmd *cobra.Command, args []string) { + LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath")) + LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target")) + + }, + Run: func(cmd *cobra.Command, args []string) { + + var systemDB pkg.PackageDatabase + + for _, a := range args { + dat, err := ioutil.ReadFile(a) + if err != nil { + Fatal("Failed reading ", a, ": ", err.Error()) + } + art, err := compiler.NewPackageArtifactFromYaml(dat) + if err != nil { + Fatal("Failed reading yaml ", a, ": ", err.Error()) + } + + if LuetCfg.GetSystem().DatabaseEngine == "boltdb" { + systemDB = pkg.NewBoltDatabase( + filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db")) + } else { + systemDB = pkg.NewInMemoryDatabase(true) + } + + files, err := art.FileList() + if err != nil { + Fatal("Failed getting file list for ", a, ": ", err.Error()) + } + + if _, err := systemDB.CreatePackage(art.GetCompileSpec().GetPackage()); err != nil { + Fatal("Failed to create ", a, ": ", err.Error()) + } + if err := systemDB.SetPackageFiles(&pkg.PackageFile{PackageFingerprint: art.GetCompileSpec().GetPackage().GetFingerPrint(), Files: files}); err != nil { + Fatal("Failed setting package files for ", a, ": ", err.Error()) + } + + Info(art.GetCompileSpec().GetPackage().HumanReadableString(), " created") + } + + }, + } + + return ans +} diff --git a/cmd/database/remove.go b/cmd/database/remove.go new file mode 100644 index 00000000..f6a47686 --- /dev/null +++ b/cmd/database/remove.go @@ -0,0 +1,65 @@ +// Copyright © 2020 Ettore Di Giacinto +// +// This program 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 2 of the License, 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . + +package cmd_database + +import ( + "path/filepath" + + . "github.com/mudler/luet/pkg/logger" + + helpers "github.com/mudler/luet/cmd/helpers" + . "github.com/mudler/luet/pkg/config" + pkg "github.com/mudler/luet/pkg/package" + + "github.com/spf13/cobra" +) + +func NewDatabaseRemoveCommand() *cobra.Command { + var ans = &cobra.Command{ + Use: "remove [package1] [package2] ...", + Short: "Remove a package from the system DB (forcefully - you normally don't want to do that)", + Args: cobra.OnlyValidArgs, + PreRun: func(cmd *cobra.Command, args []string) { + LuetCfg.Viper.BindPFlag("system.database_path", cmd.Flags().Lookup("system-dbpath")) + LuetCfg.Viper.BindPFlag("system.rootfs", cmd.Flags().Lookup("system-target")) + + }, + Run: func(cmd *cobra.Command, args []string) { + var systemDB pkg.PackageDatabase + + for _, a := range args { + pack, err := helpers.ParsePackageStr(a) + if err != nil { + Fatal("Invalid package string ", a, ": ", err.Error()) + } + + if LuetCfg.GetSystem().DatabaseEngine == "boltdb" { + systemDB = pkg.NewBoltDatabase( + filepath.Join(LuetCfg.GetSystem().GetSystemRepoDatabaseDirPath(), "luet.db")) + } else { + systemDB = pkg.NewInMemoryDatabase(true) + } + + if err := systemDB.RemovePackage(pack); err != nil { + Fatal("Failed removing ", a, ": ", err.Error()) + } + } + + }, + } + + return ans +} diff --git a/tests/integration/18_database.sh b/tests/integration/18_database.sh new file mode 100755 index 00000000..f0a9f906 --- /dev/null +++ b/tests/integration/18_database.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +export LUET_NOLOCK=true + +oneTimeSetUp() { +export tmpdir="$(mktemp -d)" +} + +oneTimeTearDown() { + rm -rf "$tmpdir" +} + +testBuild() { + mkdir $tmpdir/testbuild + luet build --tree "$ROOT_DIR/tests/fixtures/buildableseed" --destination $tmpdir/testbuild --compression gzip test/c #> /dev/null + buildst=$? + assertEquals 'builds successfully' "$buildst" "0" + assertTrue 'create package dep B' "[ -e '$tmpdir/testbuild/b-test-1.0.package.tar.gz' ]" + assertTrue 'create package' "[ -e '$tmpdir/testbuild/c-test-1.0.package.tar.gz' ]" +} + +testRepo() { + assertTrue 'no repository' "[ ! -e '$tmpdir/testbuild/repository.yaml' ]" + luet create-repo --tree "$ROOT_DIR/tests/fixtures/buildableseed" \ + --output $tmpdir/testbuild \ + --packages $tmpdir/testbuild \ + --name "test" \ + --descr "Test Repo" \ + --urls $tmpdir/testrootfs \ + --type disk > /dev/null + + createst=$? + assertEquals 'create repo successfully' "$createst" "0" + assertTrue 'create repository' "[ -e '$tmpdir/testbuild/repository.yaml' ]" +} + +testConfig() { + mkdir $tmpdir/testrootfs + cat < $tmpdir/luet.yaml +general: + debug: true +system: + rootfs: $tmpdir/testrootfs + database_path: "/" + database_engine: "boltdb" +repositories: + - name: "main" + type: "disk" + enable: true + urls: + - "$tmpdir/testbuild" +EOF + luet config --config $tmpdir/luet.yaml + res=$? + assertEquals 'config test successfully' "$res" "0" +} + +testDatabase() { + luet database create --config $tmpdir/luet.yaml $tmpdir/testbuild/c-test-1.0.metadata.yaml + #luet install --config $tmpdir/luet.yaml test/c-1.0 > /dev/null + createst=$? + assertEquals 'created package successfully' "$createst" "0" + assertTrue 'package not installed' "[ ! -e '$tmpdir/testrootfs/c' ]" + + installed=$(luet --config $tmpdir/luet.yaml search --installed .) + searchst=$? + assertEquals 'search exists successfully' "$searchst" "0" + assertContains 'contains test/c-1.0' "$installed" 'test/c-1.0' + touch $tmpdir/testrootfs/c + + luet database remove --config $tmpdir/luet.yaml test/c-1.0 + removetest=$? + assertEquals 'package removed successfully' "$removetest" "0" + assertTrue 'file not touched' "[ -e '$tmpdir/testrootfs/c' ]" + + luet database create --config $tmpdir/luet.yaml $tmpdir/testbuild/c-test-1.0.metadata.yaml + #luet install --config $tmpdir/luet.yaml test/c-1.0 > /dev/null + createst=$? + assertEquals 'created package successfully' "$createst" "0" + assertTrue 'file still present' "[ -e '$tmpdir/testrootfs/c' ]" + + luet uninstall --config $tmpdir/luet.yaml test/c + installst=$? + assertEquals 'uninstall test successfully' "$installst" "0" + assertTrue 'package uninstalled' "[ ! -e '$tmpdir/testrootfs/c' ]" +} + +# Load shUnit2. +. "$ROOT_DIR/tests/integration/shunit2"/shunit2 +