diff --git a/examples/lang/family.mcl b/examples/lang/family.mcl index 2d6f62ed..8c12a7bd 100644 --- a/examples/lang/family.mcl +++ b/examples/lang/family.mcl @@ -2,8 +2,8 @@ import "fmt" import "os" print "debian" { - msg => fmt.printf("is_debian: %t", os.is_debian()), + msg => fmt.printf("is_family_debian: %t", os.is_family_debian()), } print "redhat" { - msg => fmt.printf("is_redhat: %t", os.is_redhat()), + msg => fmt.printf("is_family_redhat: %t", os.is_family_redhat()), } diff --git a/examples/lang/pkg1.mcl b/examples/lang/pkg1.mcl index c70543e0..ab18fe97 100644 --- a/examples/lang/pkg1.mcl +++ b/examples/lang/pkg1.mcl @@ -2,5 +2,5 @@ import "os" pkg "cowsay" { state => "installed", - allowunsupported => os.is_debian() ?: true, + allowunsupported => os.is_family_debian() ?: true, } diff --git a/lang/core/os/family_func.go b/lang/core/os/family_func.go index 2f7d64f5..1f6c4882 100644 --- a/lang/core/os/family_func.go +++ b/lang/core/os/family_func.go @@ -31,11 +31,11 @@ package coreos import ( "context" - "os" "github.com/purpleidea/mgmt/lang/funcs/simple" "github.com/purpleidea/mgmt/lang/funcs/vars" "github.com/purpleidea/mgmt/lang/types" + distroUtil "github.com/purpleidea/mgmt/util/distro" ) func init() { @@ -46,129 +46,70 @@ func init() { vars.ModuleRegister(ModuleName, "family_redhat", func() vars.Value { return &types.StrValue{ - V: familyRedHat, + V: distroUtil.FamilyRedHat, } }) vars.ModuleRegister(ModuleName, "family_debian", func() vars.Value { return &types.StrValue{ - V: familyDebian, + V: distroUtil.FamilyDebian, } }) vars.ModuleRegister(ModuleName, "family_archlinux", func() vars.Value { return &types.StrValue{ - V: familyArchLinux, + V: distroUtil.FamilyArchLinux, } }) // TODO: Create a family method that will return a giant struct. - simple.ModuleRegister(ModuleName, "is_redhat", &simple.Scaffold{ + simple.ModuleRegister(ModuleName, "is_family_redhat", &simple.Scaffold{ T: types.NewType("func() bool"), - F: IsRedHat, + F: IsFamilyRedHat, }) - simple.ModuleRegister(ModuleName, "is_debian", &simple.Scaffold{ + simple.ModuleRegister(ModuleName, "is_family_debian", &simple.Scaffold{ T: types.NewType("func() bool"), - F: IsDebian, + F: IsFamilyDebian, }) - simple.ModuleRegister(ModuleName, "is_archlinux", &simple.Scaffold{ + simple.ModuleRegister(ModuleName, "is_family_archlinux", &simple.Scaffold{ T: types.NewType("func() bool"), - F: IsArchLinux, + F: IsFamilyArchLinux, }) } -const ( - familyRedHat = "redhat" - familyDebian = "debian" - familyArchLinux = "archlinux" -) - // Family returns the distro family. // TODO: Detect OS changes. func Family(ctx context.Context, input []types.Value) (types.Value, error) { - if b, err := isRedHat(ctx); err != nil { + s, err := distroUtil.Family(ctx) + if err != nil { return nil, err - } else if b { - return &types.StrValue{ - V: familyRedHat, - }, nil - } - if b, err := isDebian(ctx); err != nil { - return nil, err - } else if b { - return &types.StrValue{ - V: familyDebian, - }, nil - } - if b, err := isArchLinux(ctx); err != nil { - return nil, err - } else if b { - return &types.StrValue{ - V: familyArchLinux, - }, nil } return &types.StrValue{ - V: "", // unknown + V: s, // empty if unknown }, nil } -// IsRedHat detects if the os family is redhat. +// IsFamilyRedHat detects if the os family is redhat. // TODO: Detect OS changes. -func IsRedHat(ctx context.Context, input []types.Value) (types.Value, error) { - b, err := isRedHat(ctx) +func IsFamilyRedHat(ctx context.Context, input []types.Value) (types.Value, error) { + b, err := distroUtil.IsFamilyRedHat(ctx) return &types.BoolValue{ V: b, }, err } -// IsDebian detects if the os family is debian. +// IsFamilyDebian detects if the os family is debian. // TODO: Detect OS changes. -func IsDebian(ctx context.Context, input []types.Value) (types.Value, error) { - b, err := isDebian(ctx) +func IsFamilyDebian(ctx context.Context, input []types.Value) (types.Value, error) { + b, err := distroUtil.IsFamilyDebian(ctx) return &types.BoolValue{ V: b, }, err } -// IsArchLinux detects if the os family is archlinux. +// IsFamilyArchLinux detects if the os family is archlinux. // TODO: Detect OS changes. -func IsArchLinux(ctx context.Context, input []types.Value) (types.Value, error) { - b, err := isArchLinux(ctx) +func IsFamilyArchLinux(ctx context.Context, input []types.Value) (types.Value, error) { + b, err := distroUtil.IsFamilyArchLinux(ctx) return &types.BoolValue{ V: b, }, err } - -func isRedHat(ctx context.Context) (bool, error) { - // TODO: use ctx around io operations - _, err := os.Stat("/etc/redhat-release") - if os.IsNotExist(err) { - return false, nil - } - if err != nil { - return false, err - } - return true, nil -} - -func isDebian(ctx context.Context) (bool, error) { - // TODO: use ctx around io operations - _, err := os.Stat("/etc/debian_version") - if os.IsNotExist(err) { - return false, nil - } - if err != nil { - return false, err - } - return true, nil -} - -func isArchLinux(ctx context.Context) (bool, error) { - // TODO: use ctx around io operations - _, err := os.Stat("/etc/arch-release") - if os.IsNotExist(err) { - return false, nil - } - if err != nil { - return false, err - } - return true, nil -} diff --git a/lang/interpret_test/TestAstFunc1/importscope0.txtar b/lang/interpret_test/TestAstFunc1/importscope0.txtar index c057e5fc..ae02ec70 100644 --- a/lang/interpret_test/TestAstFunc1/importscope0.txtar +++ b/lang/interpret_test/TestAstFunc1/importscope0.txtar @@ -9,7 +9,7 @@ import "fmt" class xclass { #import "os" # this should not be required, top-level should be enough - $aaa = if os.is_debian() { "bbb" } else { "ccc" } + $aaa = if os.is_family_debian() { "bbb" } else { "ccc" } print "${aaa}" { msg => "hello", diff --git a/lang/interpret_test/TestAstFunc1/importscope1.txtar b/lang/interpret_test/TestAstFunc1/importscope1.txtar index c57de890..035c4fc0 100644 --- a/lang/interpret_test/TestAstFunc1/importscope1.txtar +++ b/lang/interpret_test/TestAstFunc1/importscope1.txtar @@ -9,11 +9,11 @@ import "fmt" class xclass { # note that `os` is not imported here - $aaa = if os.is_debian() { "bbb" } else { "ccc" } + $aaa = if os.is_family_debian() { "bbb" } else { "ccc" } print "${aaa}" { msg => "hello", } } -- OUTPUT -- -# err: errSetScope: func `os.is_debian` does not exist in this scope +# err: errSetScope: func `os.is_family_debian` does not exist in this scope diff --git a/lang/interpret_test/TestAstFunc1/importscope2.txtar b/lang/interpret_test/TestAstFunc1/importscope2.txtar index bf9b8bdf..899623da 100644 --- a/lang/interpret_test/TestAstFunc1/importscope2.txtar +++ b/lang/interpret_test/TestAstFunc1/importscope2.txtar @@ -8,7 +8,7 @@ import "fmt" class xclass { import "os" # we can also use a scoped local import - $aaa = if os.is_debian() { "bbb" } else { "ccc" } + $aaa = if os.is_family_debian() { "bbb" } else { "ccc" } print "${aaa}" { msg => "hello", diff --git a/modules/purpleidea/main.mcl b/modules/purpleidea/main.mcl index 3b3531c0..fd48efaa 100644 --- a/modules/purpleidea/main.mcl +++ b/modules/purpleidea/main.mcl @@ -31,7 +31,7 @@ import "os" # base contains the personal tweaks and utilities of james (purpleidea) class base() { - if os.is_redhat() { + if os.is_family_redhat() { pkg [ "ack", "bash-completion", @@ -53,7 +53,7 @@ class base() { state => "installed", } } - if os.is_debian() { + if os.is_family_debian() { pkg [ "ack", "bash-completion", diff --git a/util/distro/distro.go b/util/distro/distro.go index 79fe593b..cbb4d578 100644 --- a/util/distro/distro.go +++ b/util/distro/distro.go @@ -31,17 +31,39 @@ // these all in one place so that adding this data happens all in the same file. package distro +import ( + "context" + "os" +) + +const ( + // FamilyRedHat represents distros like Fedora and RHEL. + FamilyRedHat = "redhat" + + // FamilyDebian represents distros like Debian and Ubuntu. + FamilyDebian = "debian" + + // FamilyArchLinux represents primarily ArchLinux. + FamilyArchLinux = "archlinux" + + // DistroDebian is the Debian distro. + DistroDebian = "debian" + + // DistroFedora is the Fedora distro. + DistroFedora = "fedora" +) + var ( // MapDistroToBootstrapPackages is a map of distro to packages needed to // run our software. MapDistroToBootstrapPackages = map[string][]string{ // TODO: add more values - "debian": { + DistroDebian: { "libaugeas-dev", "libvirt-dev", "packagekit-tools", }, - "fedora": { + DistroFedora: { "augeas-devel", "libvirt-devel", "PackageKit", @@ -55,3 +77,62 @@ func DistroToBootstrapPackages(distro string) ([]string, bool) { l, exists := MapDistroToBootstrapPackages[distro] return l, exists } + +// Family returns the distro family. +func Family(ctx context.Context) (string, error) { + if b, err := IsFamilyRedHat(ctx); err != nil { + return "", err + } else if b { + return FamilyRedHat, nil + } + if b, err := IsFamilyDebian(ctx); err != nil { + return "", err + } else if b { + return FamilyDebian, nil + } + if b, err := IsFamilyArchLinux(ctx); err != nil { + return "", err + } else if b { + return FamilyArchLinux, nil + } + return "", nil // unknown +} + +// IsFamilyRedHat detects if the os family is redhat. +func IsFamilyRedHat(ctx context.Context) (bool, error) { + // TODO: use ctx around io operations + _, err := os.Stat("/etc/redhat-release") + if os.IsNotExist(err) { + return false, nil + } + if err != nil { + return false, err + } + return true, nil +} + +// IsFamilyDebian detects if the os family is debian. +func IsFamilyDebian(ctx context.Context) (bool, error) { + // TODO: use ctx around io operations + _, err := os.Stat("/etc/debian_version") + if os.IsNotExist(err) { + return false, nil + } + if err != nil { + return false, err + } + return true, nil +} + +// IsFamilyArchLinux detects if the os family is archlinux. +func IsFamilyArchLinux(ctx context.Context) (bool, error) { + // TODO: use ctx around io operations + _, err := os.Stat("/etc/arch-release") + if os.IsNotExist(err) { + return false, nil + } + if err != nil { + return false, err + } + return true, nil +}