|
| 1 | +package files |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "maps" |
| 6 | + "slices" |
| 7 | + "strings" |
| 8 | + |
| 9 | + "github.com/layer5io/meshkit/errors" |
| 10 | +) |
| 11 | + |
| 12 | +var ( |
| 13 | + // Error code |
| 14 | + ErrUnsupportedExtensionCode = "replace_me" |
| 15 | + ErrUnsupportedExtensionForOperationCode = "replace_me" |
| 16 | + ErrFailedToIdentifyFileCode = "replace_me" |
| 17 | + ErrSanitizingFileCode = "replace_me" |
| 18 | + ErrInvalidYamlCode = "replace_me" |
| 19 | + ErrInvalidJsonCode = "replace_me" |
| 20 | + ErrFailedToExtractTarCode = "replace_me" |
| 21 | + ErrUnsupportedFileTypeCode = "replace_me" |
| 22 | + ErrInvalidKubernetesManifestCode = "replace_me" |
| 23 | + ErrInvalidMesheryDesignCode = "replace_me" |
| 24 | + ErrInvalidHelmChartCode = "replace_me" |
| 25 | + ErrInvalidDockerComposeCode = "replace_me" |
| 26 | + ErrInvalidKustomizationCode = "replace_me" |
| 27 | + ErrFileTypeNotSupportedForDesignConversion = "replace_me" |
| 28 | +) |
| 29 | + |
| 30 | +func ErrUnsupportedExtensionForOperation(operation string, fileName string, fileExt string, supportedExtensions []string) error { |
| 31 | + sdescription := []string{ |
| 32 | + fmt.Sprintf("The file '%s' has an unsupported extension '%s' for the operation '%s'.", fileName, fileExt, operation), |
| 33 | + fmt.Sprintf("Supported extensions for this operation are: %s.", strings.Join(supportedExtensions, ", ")), |
| 34 | + } |
| 35 | + |
| 36 | + ldescription := []string{ |
| 37 | + fmt.Sprintf("The file '%s' could not be used for the operation '%s' because the extension '%s' is not supported.", fileName, operation, fileExt), |
| 38 | + fmt.Sprintf("The system is designed to handle files with the following extensions for this operation: %s.", strings.Join(supportedExtensions, ", ")), |
| 39 | + } |
| 40 | + |
| 41 | + probableCause := []string{ |
| 42 | + "The file extension does not match any of the supported formats for this operation.", |
| 43 | + "The file may have been saved with an incorrect or unsupported extension.", |
| 44 | + "The operation may have specific requirements for file types that are not met by this file.", |
| 45 | + } |
| 46 | + |
| 47 | + remedy := []string{ |
| 48 | + "Ensure the file is saved with one of the supported extensions for this operation.", |
| 49 | + "Convert the file to a supported format before attempting the operation.", |
| 50 | + "Check the documentation or requirements for the operation to verify the supported file types.", |
| 51 | + } |
| 52 | + |
| 53 | + return errors.New(ErrUnsupportedExtensionForOperationCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 54 | +} |
| 55 | + |
| 56 | +func ErrUnsupportedExtension(fileName string, fileExt string, supportedExtensionsMap map[string]bool) error { |
| 57 | + supportedExtensions := slices.Collect(maps.Keys(supportedExtensionsMap)) |
| 58 | + |
| 59 | + sdescription := []string{ |
| 60 | + fmt.Sprintf("The file '%s' has an unsupported extension: '%s'.", fileName, fileExt), |
| 61 | + fmt.Sprintf("Supported file extensions are: %s.", strings.Join(supportedExtensions, ", ")), |
| 62 | + } |
| 63 | + |
| 64 | + ldescription := []string{ |
| 65 | + fmt.Sprintf("The file '%s' could not be processed because the extension '%s' is not supported by the system.", fileName, fileExt), |
| 66 | + fmt.Sprintf("The system is designed to handle files with the following extensions: %s.", strings.Join(supportedExtensions, ", ")), |
| 67 | + } |
| 68 | + |
| 69 | + probableCause := []string{ |
| 70 | + "The file extension does not match any of the supported formats.", |
| 71 | + "The file may have been saved with an incorrect or unsupported extension.", |
| 72 | + } |
| 73 | + |
| 74 | + remedy := []string{ |
| 75 | + "Ensure the file is saved with one of the supported extensions.", |
| 76 | + "Convert the file to a supported format before attempting to process it.", |
| 77 | + } |
| 78 | + |
| 79 | + return errors.New(ErrSanitizingFileCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 80 | +} |
| 81 | + |
| 82 | +func ErrInvalidYaml(fileName string, err error) error { |
| 83 | + sdescription := []string{ |
| 84 | + fmt.Sprintf("The file '%s' contains invalid YAML syntax.", fileName), |
| 85 | + } |
| 86 | + |
| 87 | + ldescription := []string{ |
| 88 | + fmt.Sprintf("The file '%s' could not be parsed due to invalid YAML syntax.", fileName), |
| 89 | + fmt.Sprintf("Error details: %s", err.Error()), |
| 90 | + } |
| 91 | + |
| 92 | + probableCause := []string{ |
| 93 | + "The YAML file may contain syntax errors, such as incorrect indentation, missing colons, or invalid characters.", |
| 94 | + "The file may have been corrupted or improperly edited.", |
| 95 | + } |
| 96 | + |
| 97 | + remedy := []string{ |
| 98 | + "Review the YAML syntax in the file and correct any errors.", |
| 99 | + "Use a YAML validator or linter to identify and fix issues.", |
| 100 | + "Ensure the file adheres to the YAML specification.", |
| 101 | + } |
| 102 | + |
| 103 | + return errors.New(ErrInvalidYamlCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 104 | +} |
| 105 | + |
| 106 | +func ErrInvalidJson(fileName string, err error) error { |
| 107 | + sdescription := []string{ |
| 108 | + fmt.Sprintf("The file '%s' contains invalid JSON syntax.", fileName), |
| 109 | + } |
| 110 | + |
| 111 | + ldescription := []string{ |
| 112 | + fmt.Sprintf("The file '%s' could not be parsed due to invalid JSON syntax.", fileName), |
| 113 | + fmt.Sprintf("Error details: %s", err.Error()), |
| 114 | + } |
| 115 | + |
| 116 | + probableCause := []string{ |
| 117 | + "The JSON file may contain syntax errors, such as missing commas, curly braces, or square brackets.", |
| 118 | + "The file may have been corrupted or improperly edited.", |
| 119 | + "Special characters or escape sequences may not have been properly formatted.", |
| 120 | + } |
| 121 | + |
| 122 | + remedy := []string{ |
| 123 | + "Review the JSON syntax in the file and correct any errors.", |
| 124 | + "Use a JSON validator or linter to identify and fix issues.", |
| 125 | + "Ensure the file adheres to the JSON specification (e.g., double quotes for keys and strings).", |
| 126 | + "Check for common issues like trailing commas or unescaped special characters.", |
| 127 | + } |
| 128 | + |
| 129 | + return errors.New(ErrInvalidJsonCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 130 | +} |
| 131 | + |
| 132 | +func ErrFailedToExtractArchive(fileName string, err error) error { |
| 133 | + sdescription := []string{ |
| 134 | + fmt.Sprintf("Failed to extract the archive '%s'.", fileName), |
| 135 | + } |
| 136 | + |
| 137 | + ldescription := []string{ |
| 138 | + fmt.Sprintf("An error occurred while attempting to extract the TAR archive '%s'.", fileName), |
| 139 | + fmt.Sprintf("Error details: %s", err.Error()), |
| 140 | + } |
| 141 | + |
| 142 | + probableCause := []string{ |
| 143 | + "The archive may be corrupted or incomplete.", |
| 144 | + "The archive may contain unsupported compression formats or features.", |
| 145 | + "Insufficient permissions to read or write files during extraction.", |
| 146 | + "The archive may have been created with a different tool or version that is incompatible.", |
| 147 | + } |
| 148 | + |
| 149 | + remedy := []string{ |
| 150 | + "Verify that the archive is not corrupted by checking its integrity or re-downloading it.", |
| 151 | + "Ensure the archive uses a supported compression format (e.g., .zip, .tar, .tar.gz, ).", |
| 152 | + "Check that you have sufficient permissions to read the archive and write to the destination directory.", |
| 153 | + "Try using a different extraction tool or library to rule out compatibility issues.", |
| 154 | + } |
| 155 | + |
| 156 | + return errors.New(ErrFailedToExtractTarCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 157 | +} |
| 158 | + |
| 159 | +func ErrFailedToIdentifyFile(fileName string, fileExt string, identificationTrace map[string]error) error { |
| 160 | + |
| 161 | + validTypes := slices.Collect(maps.Keys(identificationTrace)) |
| 162 | + |
| 163 | + sdescription := []string{ |
| 164 | + "The file '%s' could not be identified as a supported type", |
| 165 | + } |
| 166 | + |
| 167 | + // Build a detailed trace of identification attempts |
| 168 | + var traceDetails []string |
| 169 | + for fileType, err := range identificationTrace { |
| 170 | + traceDetails = append(traceDetails, fmt.Sprintf("- Attempted to identify as '%s': %v", fileType, err)) |
| 171 | + } |
| 172 | + |
| 173 | + ldescription := []string{ |
| 174 | + fmt.Sprintf("The file '%s' was not recognized as any of the supported file types %v.", fileName, validTypes), |
| 175 | + "Identification attempts and errors:", |
| 176 | + } |
| 177 | + ldescription = append(ldescription, traceDetails...) |
| 178 | + |
| 179 | + probableCause := []string{ |
| 180 | + "The file extension does not match any of the supported types.", |
| 181 | + "The file may be corrupted or incomplete.", |
| 182 | + "The file may have been saved with an incorrect or unsupported format.", |
| 183 | + "The file may not conform to the expected structure for any supported type.", |
| 184 | + } |
| 185 | + |
| 186 | + remedy := []string{ |
| 187 | + "Ensure the file is saved with one of the supported extensions.", |
| 188 | + "Verify the integrity of the file and ensure it is not corrupted.", |
| 189 | + "Check the file's content and structure to ensure it matches one of the supported types.", |
| 190 | + "Convert the file to a supported format before attempting to process it.", |
| 191 | + } |
| 192 | + return errors.New(ErrUnsupportedFileTypeCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 193 | +} |
| 194 | + |
| 195 | +func ErrInvalidKubernetesManifest(fileName string, err error) error { |
| 196 | + sdescription := []string{ |
| 197 | + fmt.Sprintf("The file '%s' is not a valid Kubernetes manifest.", fileName), |
| 198 | + } |
| 199 | + |
| 200 | + ldescription := []string{ |
| 201 | + fmt.Sprintf("The file '%s' could not be parsed as a Kubernetes manifest due to invalid syntax or structure.", fileName), |
| 202 | + fmt.Sprintf("Error details: %s", err.Error()), |
| 203 | + } |
| 204 | + |
| 205 | + probableCause := []string{ |
| 206 | + "The file may contain invalid YAML syntax or incorrect indentation.", |
| 207 | + "The file may not conform to the Kubernetes API schema.", |
| 208 | + "The file may be missing required fields or contain unsupported fields.", |
| 209 | + } |
| 210 | + |
| 211 | + remedy := []string{ |
| 212 | + "Review the YAML syntax in the file and correct any errors.", |
| 213 | + "Use a Kubernetes YAML validator or linter to identify and fix issues.", |
| 214 | + "Ensure the file adheres to the Kubernetes API specification.", |
| 215 | + } |
| 216 | + |
| 217 | + return errors.New(ErrInvalidKubernetesManifestCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 218 | +} |
| 219 | + |
| 220 | +func ErrInvalidHelmChart(fileName string, err error) error { |
| 221 | + sdescription := []string{ |
| 222 | + fmt.Sprintf("The file '%s' is not a valid Helm chart.", fileName), |
| 223 | + } |
| 224 | + |
| 225 | + ldescription := []string{ |
| 226 | + fmt.Sprintf("The file '%s' could not be parsed as a Helm chart due to invalid structure or missing files.", fileName), |
| 227 | + fmt.Sprintf("Error details: %s", err.Error()), |
| 228 | + } |
| 229 | + |
| 230 | + probableCause := []string{ |
| 231 | + "The file may be missing required files such as 'Chart.yaml' or 'values.yaml'.", |
| 232 | + "The file may be corrupted or incomplete.", |
| 233 | + "The file may not conform to the Helm chart specification.", |
| 234 | + } |
| 235 | + |
| 236 | + remedy := []string{ |
| 237 | + "Ensure the file contains all required Helm chart files (e.g., Chart.yaml, values.yaml).", |
| 238 | + "Verify the integrity of the Helm chart archive.", |
| 239 | + "Check the Helm documentation for the correct chart structure.", |
| 240 | + } |
| 241 | + |
| 242 | + return errors.New(ErrInvalidHelmChartCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 243 | +} |
| 244 | + |
| 245 | +func ErrInvalidDockerCompose(fileName string, err error) error { |
| 246 | + sdescription := []string{ |
| 247 | + fmt.Sprintf("The file '%s' is not a valid Docker Compose file.", fileName), |
| 248 | + } |
| 249 | + |
| 250 | + ldescription := []string{ |
| 251 | + fmt.Sprintf("The file '%s' could not be parsed as a Docker Compose file due to invalid syntax or structure.", fileName), |
| 252 | + fmt.Sprintf("Error details: %s", err.Error()), |
| 253 | + } |
| 254 | + |
| 255 | + probableCause := []string{ |
| 256 | + "The file may contain invalid YAML syntax or incorrect indentation.", |
| 257 | + "The file may not conform to the Docker Compose specification.", |
| 258 | + "The file may be missing required fields or contain unsupported fields.", |
| 259 | + } |
| 260 | + |
| 261 | + remedy := []string{ |
| 262 | + "Review the YAML syntax in the file and correct any errors.", |
| 263 | + "Use a Docker Compose validator or linter to identify and fix issues.", |
| 264 | + "Ensure the file adheres to the Docker Compose specification.", |
| 265 | + } |
| 266 | + |
| 267 | + return errors.New(ErrInvalidDockerComposeCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 268 | +} |
| 269 | + |
| 270 | +func ErrInvalidKustomization(fileName string, err error) error { |
| 271 | + sdescription := []string{ |
| 272 | + fmt.Sprintf("The file '%s' is not a valid Kustomization file.", fileName), |
| 273 | + } |
| 274 | + |
| 275 | + ldescription := []string{ |
| 276 | + fmt.Sprintf("The file '%s' could not be parsed as a Kustomization file due to invalid syntax or structure.", fileName), |
| 277 | + fmt.Sprintf("Error details: %s", err.Error()), |
| 278 | + } |
| 279 | + |
| 280 | + probableCause := []string{ |
| 281 | + "The file may be missing required fields such as 'resources' or 'bases'.", |
| 282 | + "The file may contain invalid YAML syntax or incorrect indentation.", |
| 283 | + "The file may not conform to the Kustomize specification.", |
| 284 | + } |
| 285 | + |
| 286 | + remedy := []string{ |
| 287 | + "Review the YAML syntax in the file and correct any errors.", |
| 288 | + "Ensure the file contains all required fields for Kustomization.", |
| 289 | + "Check the Kustomize documentation for the correct file structure.", |
| 290 | + } |
| 291 | + |
| 292 | + return errors.New(ErrInvalidKustomizationCode, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 293 | +} |
| 294 | + |
| 295 | +func ErrUnsupportedFileTypeForConversionToDesign(fileName string, fileType string) error { |
| 296 | + sdescription := []string{ |
| 297 | + fmt.Sprintf("The file '%s' of type '%s' is not supported for conversion to a design", fileName, fileType), |
| 298 | + } |
| 299 | + |
| 300 | + ldescription := []string{ |
| 301 | + fmt.Sprintf("The file '%s' of type '%s' cannot be converted to design. Supported formats are: meshery-design, helm-chart, k8s-manifest, docker-compose.", fileName, fileType), |
| 302 | + } |
| 303 | + |
| 304 | + probableCause := []string{ |
| 305 | + "File doesn't match any supported IAC files", |
| 306 | + "Attempting to convert a file type not enabled for design conversion", |
| 307 | + } |
| 308 | + |
| 309 | + remedy := []string{ |
| 310 | + "Verify the file format matches one of the supported types", |
| 311 | + "Convert the file to a supported format before processing", |
| 312 | + } |
| 313 | + |
| 314 | + return errors.New(ErrFileTypeNotSupportedForDesignConversion, errors.Critical, sdescription, ldescription, probableCause, remedy) |
| 315 | +} |
| 316 | + |
| 317 | +var ( |
| 318 | + ErrNoTarInsideOCICode = "replace_me" |
| 319 | + ErrEmptyOCIImageCode = "replace_me" |
| 320 | + ErrUnCompressOCIArtifactCode = "replace_me" |
| 321 | + ErrWaklingLocalDirectoryCode = "replace_me" |
| 322 | + ErrDecodePatternCode = "replace_me" |
| 323 | +) |
| 324 | + |
| 325 | +// OCI Parsing errors |
| 326 | + |
| 327 | +func ErrNoTarInsideOCi() error { |
| 328 | + return errors.New(ErrNoTarInsideOCICode, errors.Alert, []string{"No tar file found inside OCI image"}, []string{"Unable to locate the compressed file(.tar.gz) inside the OCI image."}, []string{"The OCI image does not contain a ziped file."}, []string{"Verify that the OCI image contains a ziped file."}) |
| 329 | +} |
| 330 | +func ErrEmptyOCIImage(err error) error { |
| 331 | + return errors.New(ErrEmptyOCIImageCode, errors.Alert, []string{}, []string{}, []string{}, []string{}) |
| 332 | +} |
| 333 | + |
| 334 | +func ErrUnCompressOCIArtifact(err error) error { |
| 335 | + return errors.New(ErrUnCompressOCIArtifactCode, errors.Alert, []string{"Failed to uncompress OCI artifact"}, []string{err.Error()}, []string{"unable to uncompress OCI artifact", "OCI artifact may be corrupted"}, []string{"check if the OCI artifact is valid and not corrupted"}) |
| 336 | +} |
| 337 | + |
| 338 | +func ErrWaklingLocalDirectory(err error) error { |
| 339 | + return errors.New(ErrWaklingLocalDirectoryCode, errors.Alert, []string{"Failed to walk local directory"}, []string{err.Error()}, []string{"unable to walk local directory", "local directory may be corrupted"}, []string{"check if the local directory is valid and not corrupted"}) |
| 340 | +} |
| 341 | + |
| 342 | +func ErrDecodePattern(err error) error { |
| 343 | + return errors.New(ErrDecodePatternCode, errors.Alert, []string{"Error failed to decode design data into go slice"}, []string{err.Error()}, []string{}, []string{}) |
| 344 | +} |
0 commit comments