summaryrefslogtreecommitdiffstats
path: root/lib/puppet/application/resource.rb
blob: f914a1b53ce01d6f899f7894ae0162a8973d8c98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
require 'puppet'
require 'puppet/application'
require 'facter'

Puppet::Application.new(:resource) do

    should_not_parse_config

    attr_accessor :host, :extra_params

    preinit do
        @extra_params = []
        @host = nil
        Facter.loadfacts
    end

    option("--debug","-d")
    option("--verbose","-v")
    option("--edit","-e")

    option("--host HOST","-H") do |arg|
        @host = arg
    end

    option("--types", "-t") do |arg|
        types = []
        Puppet::Type.loadall
        Puppet::Type.eachtype do |t|
            next if t.name == :component
            types << t.name.to_s
        end
        puts types.sort
        exit
    end

    option("--param PARAM", "-p") do |arg|
        @extra_params << arg.to_sym
    end

    command(:main) do
        type = ARGV.shift or raise "You must specify the type to display"
        typeobj = Puppet::Type.type(type) or raise "Could not find type #{type}"
        name = ARGV.shift
        params = {}
        ARGV.each do |setting|
            if setting =~ /^(\w+)=(.+)$/
                params[$1] = $2
            else
                raise "Invalid parameter setting %s" % setting
            end
        end

        if options[:edit] and @host
            raise "You cannot edit a remote host"
        end

        properties = typeobj.properties.collect { |s| s.name }

        format = proc {|trans|
            trans.dup.collect do |param, value|
                if value.nil? or value.to_s.empty?
                    trans.delete(param)
                elsif value.to_s == "absent" and param.to_s != "ensure"
                    trans.delete(param)
                end

                unless properties.include?(param) or @extra_params.include?(param)
                    trans.delete(param)
                end
            end
            trans.to_manifest
        }

        text = if @host
            client = Puppet::Network::Client.resource.new(:Server => @host, :Port => Puppet[:puppetport])
            unless client.read_cert
                raise "client.read_cert failed"
            end
            begin
                # They asked for a single resource.
                if name
                    transbucket = [client.describe(type, name)]
                else
                    # Else, list the whole thing out.
                    transbucket = client.instances(type)
                end
            rescue Puppet::Network::XMLRPCClientError => exc
                raise "client.list(#{type}) failed: #{exc.message}"
            end
            transbucket.sort { |a,b| a.name <=> b.name }.collect(&format)
        else
            if name
                obj = typeobj.instances.find { |o| o.name == name } || typeobj.new(:name => name, :check => properties)
                vals = obj.retrieve

                unless params.empty?
                    params.each do |param, value|
                        obj[param] = value
                    end
                    catalog = Puppet::Resource::Catalog.new
                    catalog.add_resource obj
                    begin
                        catalog.apply
                    rescue => detail
                        if Puppet[:trace]
                            puts detail.backtrace
                        end
                    end

                end
                [format.call(obj.to_trans(true))]
            else
                typeobj.instances.collect do |obj|
                    next if ARGV.length > 0 and ! ARGV.include? obj.name
                    trans = obj.to_trans(true)
                    format.call(trans)
                end
            end
        end.compact.join("\n")

        if options[:edit]
            file = "/tmp/x2puppet-#{Process.pid}.pp"
            begin
                File.open(file, "w") do |f|
                    f.puts text
                end
                ENV["EDITOR"] ||= "vi"
                system(ENV["EDITOR"], file)
                system("puppet -v " + file)
            ensure
                #if FileTest.exists? file
                #    File.unlink(file)
                #end
            end
        else
            puts text
        end
    end

    setup do
        Puppet::Util::Log.newdestination(:console)

        # Now parse the config
        Puppet.parse_config

        if options[:debug]
            Puppet::Util::Log.level = :debug
        elsif options[:verbose]
            Puppet::Util::Log.level = :info
        end
    end
end