11require 'tempfile'
22require 'base64'
3- require 'json'
43
54Puppet ::Type . type ( :podman_secret ) . provide ( :podman ) do
65 desc 'Podman secret provider'
76
87 commands podman : 'podman'
98
109 def exists?
11- podman ( 'secret' , 'inspect' , resource [ :name ] )
12- true
10+ execute_podman_command ( 'secret' , 'inspect' , resource [ :name ] )
11+
12+ if resource [ :secret ]
13+ secret == resource [ :secret ]
14+ elsif resource [ :path ]
15+ new_secret = File . read ( resource [ :path ] )
16+ secret == new_secret
17+ end
1318 rescue Puppet ::ExecutionFailure
1419 false
1520 end
1621
1722 def secret
18- return nil unless exists?
19-
20- begin
21- output = execute_podman_command ( [ 'secret' , 'inspect' , '--showsecret' , resource [ :name ] ] , capture_output : true )
22- secret_data = JSON . parse ( output )
23- secret_data . first [ 'SecretData' ]
24- rescue StandardError => e
25- Puppet . debug ( "Failed to retrieve secret content: #{ e . message } " )
26- nil
27- end
28- end
29-
30- def secret = ( _value )
31- # Podman doesn't support updating secrets in place
32- # We need to remove and recreate the secret
33- if exists?
34- destroy
35- end
36- create
23+ output = execute_podman_command (
24+ 'secret' ,
25+ 'inspect' ,
26+ resource [ :name ] ,
27+ '--showsecret' ,
28+ '--format' ,
29+ '{{.SecretData}}' ,
30+ )
31+
32+ output . chomp
33+ rescue StandardError => e
34+ Puppet . debug ( "Failed to retrieve secret content: #{ e . message } " )
35+ nil
3736 end
3837
3938 def create
39+ destroy if exists?
40+
4041 args = [ 'secret' , 'create' ]
4142
4243 # Process flags
@@ -68,7 +69,7 @@ def create
6869 end
6970
7071 def destroy
71- podman ( 'secret' , 'rm' , resource [ :name ] )
72+ execute_podman_command ( 'secret' , 'rm' , resource [ :name ] )
7273 end
7374
7475 private
@@ -86,7 +87,7 @@ def create_secret_from_content(args, secret_content)
8687 end
8788 end
8889
89- def execute_podman_command ( args , capture_output : false )
90+ def execute_podman_command ( * args )
9091 if resource [ :user ]
9192 # Set up environment for rootless user
9293 user_info = Etc . getpwnam ( resource [ :user ] )
@@ -95,20 +96,33 @@ def execute_podman_command(args, capture_output: false)
9596 'XDG_RUNTIME_DIR' => "/run/user/#{ user_info . uid } " ,
9697 }
9798
98- result = Puppet ::Util ::Execution . execute (
99+ Puppet ::Util ::Execution . execute (
99100 [ command ( :podman ) ] + args ,
100101 uid : user_info . uid ,
101102 gid : user_info . gid ,
102103 custom_environment : env ,
103104 cwd : user_info . dir ,
104105 failonfail : true ,
106+ combine : false ,
105107 )
106- capture_output ? result : nil
107- elsif capture_output
108- podman ( *args )
109108 else
110- podman ( *args )
111- nil
109+ # This intentionally avoids commands: podman usage in order to define
110+ # the command ourselves and pass combine => false. This prevents stdout
111+ # and stderr from being combined and breaking the output from podman.
112+ # For example, secrets are printed as JSON, but if stderr is present,
113+ # such as a warning, the JSON will not be parseable.
114+ podman = Puppet ::Provider ::Command . new (
115+ 'podman' ,
116+ command ( :podman ) ,
117+ Puppet ::Util ,
118+ Puppet ::Util ::Execution ,
119+ {
120+ failonfail : true ,
121+ combine : false ,
122+ } ,
123+ )
124+
125+ podman . execute ( args )
112126 end
113127 end
114128end
0 commit comments