@@ -88,14 +88,20 @@ protected String extractUserDataHeader(String userdata) {
8888 .filter (x -> (x .startsWith ("#" ) && !x .startsWith ("##" )) || (x .startsWith ("Content-Type:" )))
8989 .collect (Collectors .toList ());
9090 if (CollectionUtils .isEmpty (lines )) {
91- throw new CloudRuntimeException ("Failed to detect the user data format type as it " +
92- "does not contain a header" ) ;
91+ LOGGER . debug ("Failed to detect the user data format type as it does not contain a header" );
92+ return null ;
9393 }
9494 return lines .get (0 );
9595 }
9696
97- protected FormatType mapUserDataHeaderToFormatType (String header ) {
98- if (header .equalsIgnoreCase ("#cloud-config" )) {
97+ protected FormatType mapUserDataHeaderToFormatType (String header , FormatType defaultFormatType ) {
98+ if (StringUtils .isBlank (header )) {
99+ if (defaultFormatType == null ) {
100+ throw new CloudRuntimeException ("Failed to detect the user data format type as it does not contain a header" );
101+ }
102+ LOGGER .debug (String .format ("Empty header for userdata, using the default format type: %s" , defaultFormatType .name ()));
103+ return defaultFormatType ;
104+ } else if (header .equalsIgnoreCase ("#cloud-config" )) {
99105 return FormatType .CLOUD_CONFIG ;
100106 } else if (header .startsWith ("#!" )) {
101107 return FormatType .BASH_SCRIPT ;
@@ -115,17 +121,19 @@ protected FormatType mapUserDataHeaderToFormatType(String header) {
115121
116122 /**
117123 * Detect the user data type
124+ * @param userdata the userdata string to detect the type
125+ * @param defaultFormatType if not null, then use it in case the header does not exist in the userdata, otherwise fail
118126 * Reference: <a href="https://canonical-cloud-init.readthedocs-hosted.com/en/latest/explanation/format.html#user-data-formats" />
119127 */
120- protected FormatType getUserDataFormatType (String userdata ) {
128+ protected FormatType getUserDataFormatType (String userdata , FormatType defaultFormatType ) {
121129 if (StringUtils .isBlank (userdata )) {
122130 String msg = "User data expected but provided empty user data" ;
123131 LOGGER .error (msg );
124132 throw new CloudRuntimeException (msg );
125133 }
126134
127135 String header = extractUserDataHeader (userdata );
128- return mapUserDataHeaderToFormatType (header );
136+ return mapUserDataHeaderToFormatType (header , defaultFormatType );
129137 }
130138
131139 private String getContentType (String userData , FormatType formatType ) throws MessagingException {
@@ -234,7 +242,9 @@ private NoIdMimeMessage createMultipartMessageAddingUserdata(String userData, Fo
234242 }
235243
236244 private String simpleAppendSameFormatTypeUserData (String userData1 , String userData2 ) {
237- return String .format ("%s\n \n %s" , userData1 , userData2 .substring (userData2 .indexOf ('\n' )+1 ));
245+ String userdata2Header = extractUserDataHeader (userData2 );
246+ int beginIndex = StringUtils .isNotBlank (userdata2Header ) ? userData2 .indexOf ('\n' )+1 : 0 ;
247+ return String .format ("%s\n \n %s" , userData1 , userData2 .substring (beginIndex ));
238248 }
239249
240250 private void checkGzipAppend (String encodedUserData1 , String encodedUserData2 ) {
@@ -249,8 +259,8 @@ public String appendUserData(String encodedUserData1, String encodedUserData2) {
249259 checkGzipAppend (encodedUserData1 , encodedUserData2 );
250260 String userData1 = new String (Base64 .decodeBase64 (encodedUserData1 ));
251261 String userData2 = new String (Base64 .decodeBase64 (encodedUserData2 ));
252- FormatType formatType1 = getUserDataFormatType (userData1 );
253- FormatType formatType2 = getUserDataFormatType (userData2 );
262+ FormatType formatType1 = getUserDataFormatType (userData1 , null );
263+ FormatType formatType2 = getUserDataFormatType (userData2 , formatType1 );
254264 if (formatType1 .equals (formatType2 ) && List .of (FormatType .CLOUD_CONFIG , FormatType .BASH_SCRIPT ).contains (formatType1 )) {
255265 return simpleAppendSameFormatTypeUserData (userData1 , userData2 );
256266 }
0 commit comments