| 1081 | |
| 1082 | #[must_use] |
| 1083 | pub fn validate_profile_set( |
| 1084 | profiles: &[(String, ProviderTypeProfile)], |
| 1085 | ) -> Vec<ProfileValidationDiagnostic> { |
| 1086 | let mut diagnostics = Vec::new(); |
| 1087 | let mut ids = HashSet::new(); |
| 1088 | for (source, profile) in profiles { |
| 1089 | let raw_profile_id = profile.id.as_str(); |
| 1090 | let profile_id = raw_profile_id.trim(); |
| 1091 | if profile_id.is_empty() { |
| 1092 | diagnostics.push(ProfileValidationDiagnostic::error( |
| 1093 | source, |
| 1094 | "", |
| 1095 | "id", |
| 1096 | "provider profile id is required", |
| 1097 | )); |
| 1098 | } else if normalize_profile_id(raw_profile_id).as_deref() != Some(raw_profile_id) { |
| 1099 | diagnostics.push(ProfileValidationDiagnostic::error( |
| 1100 | source, |
| 1101 | profile_id, |
| 1102 | "id", |
| 1103 | "provider profile id must be lowercase kebab-case using only a-z, 0-9, and '-'", |
| 1104 | )); |
| 1105 | } else if !ids.insert(profile_id.to_string()) { |
| 1106 | diagnostics.push(ProfileValidationDiagnostic::error( |
| 1107 | source, |
| 1108 | profile_id, |
| 1109 | "id", |
| 1110 | format!("duplicate provider profile id: {profile_id}"), |
| 1111 | )); |
| 1112 | } |
| 1113 | |
| 1114 | let mut credential_names = HashSet::new(); |
| 1115 | for credential in &profile.credentials { |
| 1116 | let credential_name = credential.name.trim(); |
| 1117 | if credential_name.is_empty() { |
| 1118 | diagnostics.push(ProfileValidationDiagnostic::error( |
| 1119 | source, |
| 1120 | profile_id, |
| 1121 | "credentials.name", |
| 1122 | "credential name is required", |
| 1123 | )); |
| 1124 | } else if !credential_names.insert(credential_name.to_string()) { |
| 1125 | diagnostics.push(ProfileValidationDiagnostic::error( |
| 1126 | source, |
| 1127 | profile_id, |
| 1128 | "credentials.name", |
| 1129 | format!("duplicate credential name: {credential_name}"), |
| 1130 | )); |
| 1131 | } |
| 1132 | } |
| 1133 | |
| 1134 | let mut discovery_credentials = HashSet::new(); |
| 1135 | for (index, credential_name) in profile.discovery.credentials.iter().enumerate() { |
| 1136 | let credential_name = credential_name.trim(); |
| 1137 | if credential_name.is_empty() { |
| 1138 | diagnostics.push(ProfileValidationDiagnostic::error( |
| 1139 | source, |
| 1140 | profile_id, |