1313# See the License for the specific language governing permissions and
1414# limitations under the License.
1515
16- from tower_cli import models
16+ import six
17+ import os
18+
19+ from tower_cli import models , exceptions as exc , get_resource
1720from tower_cli .cli import types
21+ from tower_cli .utils import debug , str_to_bool
1822
1923
2024class Resource (models .Resource ):
@@ -32,5 +36,82 @@ class Resource(models.Resource):
3236 team = models .Field (display = False , type = types .Related ('team' ), required = False , no_lookup = True )
3337 organization = models .Field (display = False , type = types .Related ('organization' ), required = False )
3438
39+ # Core functionality
3540 credential_type = models .Field (type = types .Related ('credential_type' ))
3641 inputs = models .Field (type = types .StructuredInput (), required = False , display = False )
42+
43+ # Fields for reverse compatibility
44+ subinput = models .Field (
45+ required = False , nargs = 2 , multiple = True , display = False ,
46+ help_text = 'A key and value to be combined into the credential inputs JSON data.'
47+ ' Start the value with "@" to obtain from a file.\n '
48+ 'Example: `--subinput ssh_key_data @filename` would apply an SSH private key'
49+ )
50+
51+ def update_from_existing (self , kwargs , existing_data ):
52+ subinputs = kwargs .pop ('subinput' , ())
53+ if not subinputs :
54+ return super (Resource , self ).update_from_existing (kwargs , existing_data )
55+
56+ inputs = {}
57+ if kwargs .get ('inputs' ):
58+ inputs = kwargs ['inputs' ].copy ()
59+ elif existing_data .get ('inputs' ):
60+ inputs = existing_data ['inputs' ].copy ()
61+
62+ ct_pk = None
63+ if existing_data :
64+ ct_pk = existing_data .get ('credential_type' )
65+ else :
66+ ct_pk = kwargs .get ('credential_type' )
67+ if not ct_pk :
68+ debug .log ('Could not apply subinputs because of unknown credential type' )
69+ return super (Resource , self ).update_from_existing (kwargs , existing_data )
70+
71+ ct_res = get_resource ('credential_type' )
72+ schema = ct_res .get (ct_pk )['inputs' ].get ('fields' , [])
73+ schema_map = {}
74+ for element in schema :
75+ schema_map [element .get ('id' , '' )] = element
76+
77+ for key , raw_value in subinputs :
78+ if kwargs and kwargs .get (key , {}).get (key ):
79+ raise exc .BadRequest (
80+ 'Field {} specified in both --subinput and --inputs.' .format (key )
81+ )
82+
83+ # Read from a file if starts with "@"
84+ if raw_value .startswith ('@' ):
85+ filename = os .path .expanduser (raw_value [1 :])
86+ with open (filename , 'r' ) as f :
87+ value = f .read ()
88+ else :
89+ value = raw_value
90+
91+ # Type conversion
92+ if key not in schema_map :
93+ debug .log ('Credential type inputs:\n {}' .format (schema ))
94+ raise exc .BadRequest (
95+ 'Field {} is not allowed by credential type inputs.' .format (key )
96+ )
97+ type_str = schema_map [key ].get ('type' , 'string' )
98+
99+ converters = {
100+ 'string' : six .text_type ,
101+ 'boolean' : str_to_bool
102+ }
103+ if type_str not in converters :
104+ raise exc .BadRequest (
105+ 'Credential type {} input {} uses an unrecognized type: {}.' .format (
106+ ct_pk , key , type_str )
107+ )
108+ converter = converters [type_str ]
109+ try :
110+ value = converter (value )
111+ except Exception as e :
112+ raise exc .BadRequest (
113+ 'Field {} in --subinput is not type {} specified by credential type '
114+ '{} inputs.\n (error: {})' .format (key , type_str , ct_pk , e )
115+ )
116+ inputs [key ] = value
117+ kwargs ['inputs' ] = inputs
0 commit comments