@@ -85,14 +85,20 @@ protected String extractUserDataHeader(String userdata) {
8585 .filter (x -> (x .startsWith ("#" ) && !x .startsWith ("##" )) || (x .startsWith ("Content-Type:" )))
8686 .collect (Collectors .toList ());
8787 if (CollectionUtils .isEmpty (lines )) {
88- throw new CloudRuntimeException ("Failed to detect the user data format type as it " +
89- "does not contain a header" ) ;
88+ LOGGER . debug ("Failed to detect the user data format type as it does not contain a header" );
89+ return null ;
9090 }
9191 return lines .get (0 );
9292 }
9393
94- protected FormatType mapUserDataHeaderToFormatType (String header ) {
95- if (header .equalsIgnoreCase ("#cloud-config" )) {
94+ protected FormatType mapUserDataHeaderToFormatType (String header , FormatType defaultFormatType ) {
95+ if (StringUtils .isBlank (header )) {
96+ if (defaultFormatType == null ) {
97+ throw new CloudRuntimeException ("Failed to detect the user data format type as it does not contain a header" );
98+ }
99+ LOGGER .debug (String .format ("Empty header for userdata, using the default format type: %s" , defaultFormatType .name ()));
100+ return defaultFormatType ;
101+ } else if (header .equalsIgnoreCase ("#cloud-config" )) {
96102 return FormatType .CLOUD_CONFIG ;
97103 } else if (header .startsWith ("#!" )) {
98104 return FormatType .BASH_SCRIPT ;
@@ -112,17 +118,19 @@ protected FormatType mapUserDataHeaderToFormatType(String header) {
112118
113119 /**
114120 * Detect the user data type
121+ * @param userdata the userdata string to detect the type
122+ * @param defaultFormatType if not null, then use it in case the header does not exist in the userdata, otherwise fail
115123 * Reference: <a href="https://canonical-cloud-init.readthedocs-hosted.com/en/latest/explanation/format.html#user-data-formats" />
116124 */
117- protected FormatType getUserDataFormatType (String userdata ) {
125+ protected FormatType getUserDataFormatType (String userdata , FormatType defaultFormatType ) {
118126 if (StringUtils .isBlank (userdata )) {
119127 String msg = "User data expected but provided empty user data" ;
120128 logger .error (msg );
121129 throw new CloudRuntimeException (msg );
122130 }
123131
124132 String header = extractUserDataHeader (userdata );
125- return mapUserDataHeaderToFormatType (header );
133+ return mapUserDataHeaderToFormatType (header , defaultFormatType );
126134 }
127135
128136 private String getContentType (String userData , FormatType formatType ) throws MessagingException {
@@ -231,7 +239,9 @@ private NoIdMimeMessage createMultipartMessageAddingUserdata(String userData, Fo
231239 }
232240
233241 private String simpleAppendSameFormatTypeUserData (String userData1 , String userData2 ) {
234- return String .format ("%s\n \n %s" , userData1 , userData2 .substring (userData2 .indexOf ('\n' )+1 ));
242+ String userdata2Header = extractUserDataHeader (userData2 );
243+ int beginIndex = StringUtils .isNotBlank (userdata2Header ) ? userData2 .indexOf ('\n' )+1 : 0 ;
244+ return String .format ("%s\n \n %s" , userData1 , userData2 .substring (beginIndex ));
235245 }
236246
237247 private void checkGzipAppend (String encodedUserData1 , String encodedUserData2 ) {
@@ -246,8 +256,8 @@ public String appendUserData(String encodedUserData1, String encodedUserData2) {
246256 checkGzipAppend (encodedUserData1 , encodedUserData2 );
247257 String userData1 = new String (Base64 .decodeBase64 (encodedUserData1 ));
248258 String userData2 = new String (Base64 .decodeBase64 (encodedUserData2 ));
249- FormatType formatType1 = getUserDataFormatType (userData1 );
250- FormatType formatType2 = getUserDataFormatType (userData2 );
259+ FormatType formatType1 = getUserDataFormatType (userData1 , null );
260+ FormatType formatType2 = getUserDataFormatType (userData2 , formatType1 );
251261 if (formatType1 .equals (formatType2 ) && List .of (FormatType .CLOUD_CONFIG , FormatType .BASH_SCRIPT ).contains (formatType1 )) {
252262 return simpleAppendSameFormatTypeUserData (userData1 , userData2 );
253263 }
0 commit comments