# # Copyright 2014-2018 Chef Software, Inc. # # 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 # # http://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. # require "thor" unless defined?(Thor) require "omnibus" require "ffi_yajl" unless defined?(FFI_Yajl) module Omnibus class CLI < Command::Base # This is the main entry point for the CLI. It exposes the method # {#execute!} to start the CLI. # # @note the arity of {#initialize} and {#execute!} are extremely important # for testing purposes. It is a requirement to perform in-process testing # with Aruba. In process testing is much faster than spawning a new Ruby # process for each test. class Runner include Logging def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel) @argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel end def execute! $stdin = @stdin $stdout = @stdout $stderr = @stderr Omnibus::CLI.start(@argv) @kernel.exit(0) rescue Omnibus::Error => e error = Omnibus.ui.set_color(e.message, :red) backtrace = Omnibus.ui.set_color("\n" + e.backtrace.join("\n "), :red) Omnibus.ui.error(error) Omnibus.ui.error(backtrace) if e.respond_to?(:status_code) @kernel.exit(e.status_code) else @kernel.exit(1) end end end map %w{-v --version} => "version" # # Build an Omnibus project or software definition. # # $ omnibus build chefdk # method_option :output_manifest, desc: "Create version-manifest.json in current directory at the end of the build", type: :boolean, default: true method_option :use_manifest, desc: "Use the given manifest when downloading software sources.", type: :string, default: nil method_option :populate_s3_cache, desc: "Populate the S3 cache.", type: :boolean, default: false desc "build PROJECT", "Build the given Omnibus project" def build(name) manifest = if @options[:use_manifest] Omnibus::Manifest.from_file(@options[:use_manifest]) else nil end project = Project.load(name, manifest) say("Building #{project.name} #{project.build_version}...") Omnibus::S3Cache.populate if @options[:populate_s3_cache] && !Omnibus::S3Cache.fetch_missing.empty? begin project.download rescue Config.use_s3_caching(false) if Config.use_s3_caching project = Project.load(name, nil) project.download end project.build if @options[:output_manifest] FileUtils.mkdir_p("pkg") File.open(::File.join("pkg", "version-manifest.json"), "w") do |f| f.write(FFI_Yajl::Encoder.encode(project.built_manifest.to_hash, pretty: true)) end end end register(Command::ChangeLog, "changelog", "changelog [COMMAND]", "Create and view changelogs") CLI.tasks["changelog"].options = Command::ChangeLog.class_options # # Generate a version manifest for the given project definition # # $ omnibus manifest PROJECT # method_option :os, desc: "An os name in Ohai form. Defaults to the current os.", type: :string method_option :platform_family, desc: "A platform family string in Ohai form. Defaults to the current platform_family.", type: :string method_option :platform, desc: "A platform string in Ohai form. Defaults to the current platform.", type: :string method_option :platform_version, desc: "A platform version string in Ohai form. Defaults to the current platform.", type: :string method_option :architecture, desc: "The target architecture: x86, x64, powerpc. Defaults to the current architecture." desc "manifest PROJECT", "Print a manifest for the given Omnibus project" def manifest(name) # Override ohai information Ohai["os"] = @options[:os] if @options[:os] Ohai["platform_family"] = @options[:platform_family] if @options[:platform_family] Ohai["platform"] = @options[:platform] if @options[:platform] Ohai["platform_version"] = @options[:platform_version] if @options[:platform_version] Ohai["kernel"]["machine"] = @options[:architecture] if @options[:architecture] puts FFI_Yajl::Encoder.encode(Project.load(name).built_manifest.to_hash, pretty: true) end # # Perform cache management functions. # # $ omnibus cache list # register(Command::Cache, "cache", "cache [COMMAND]", "Manage the cache") CLI.tasks["cache"].options = Command::Cache.class_options # # Clean the Omnibus project. # # $ omnibus clean chefdk # register(Cleaner, "clean", "clean PROJECT", "Clean the Omnibus project") CLI.tasks["clean"].options = Cleaner.class_options # # Initialize a new Omnibus project. # # $ omnibus new NAME # register(Generator, "new", "new NAME", "Initialize a new Omnibus project") CLI.tasks["new"].options = Generator.class_options # # List the Omnibus projects available from "here". # # $ omnibus list # desc "list", "List the Omnibus projects" def list if Omnibus.projects.empty? say("There are no Omnibus projects!") else say("Omnibus projects:") Omnibus.projects.sort.each do |project| say(" * #{project.name} (#{project.build_version})") end end end # # Publish Omnibus package(s) to a backend. # # $ omnibus publish s3 pkg/*chef* # register(Command::Publish, "publish", "publish [COMMAND]", "Publish Omnibus packages to a backend") CLI.tasks["publish"].options = Command::Publish.class_options # # Display version information. # # $ omnibus version # desc "version", "Display version information", hide: true def version say("Omnibus v#{Omnibus::VERSION}") end end end