| 207 | } |
| 208 | |
| 209 | func (s *Spec) Validate() error { |
| 210 | if len(s.Bucket) == 0 { |
| 211 | return errors.New("`bucket` is required") |
| 212 | } |
| 213 | if len(s.Region) == 0 { |
| 214 | return errors.New("`region` is required") |
| 215 | } |
| 216 | |
| 217 | if len(s.Path) == 0 { |
| 218 | return errors.New("`path` is required") |
| 219 | } |
| 220 | if path.IsAbs(s.Path) { |
| 221 | return errors.New("`path` should not start with a \"/\"") |
| 222 | } |
| 223 | if s.Path != path.Clean(s.Path) { |
| 224 | return errors.New("`path` should not contain relative paths or duplicate slashes") |
| 225 | } |
| 226 | |
| 227 | if s.GenerateEmptyObjects && s.Format != filetypes.FormatTypeParquet { |
| 228 | return errors.New("`write_empty_objects_for_empty_tables` can only be used with `parquet` format") |
| 229 | } |
| 230 | |
| 231 | if s.LocalProfile != "" && (s.Credentials != nil && (s.Credentials.RoleARN != "" || s.Credentials.RoleSessionName != "" || s.Credentials.ExternalID != "" || s.Credentials.LocalProfile != "")) { |
| 232 | return errors.New("`local_profile` cannot be used with `credentials`") |
| 233 | } |
| 234 | if s.NoRotate { |
| 235 | if strings.Contains(s.Path, varUUID) { |
| 236 | return fmt.Errorf("`path` should not contain %s when `no_rotate` = true", varUUID) |
| 237 | } |
| 238 | |
| 239 | if (s.BatchSize != nil && *s.BatchSize > 0) || (s.BatchSizeBytes != nil && *s.BatchSizeBytes > 0) || (s.BatchTimeout != nil && s.BatchTimeout.Duration() > 0) { |
| 240 | return errors.New("`no_rotate` cannot be used with non-zero `batch_size`, `batch_size_bytes` or `batch_timeout_ms`") |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | if !strings.Contains(s.Path, varUUID) && s.batchingEnabled() { |
| 245 | return fmt.Errorf("`path` should contain %s when using a non-zero `batch_size`, `batch_size_bytes` or `batch_timeout_ms`", varUUID) |
| 246 | } |
| 247 | |
| 248 | if s.ACL != "" { |
| 249 | acl := types.ObjectCannedACL(s.ACL) |
| 250 | cannedACLS := acl.Values() |
| 251 | |
| 252 | if !slices.Contains(cannedACLS, acl) { |
| 253 | return fmt.Errorf("invalid `acl` value: %s", s.ACL) |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | // required for s.FileSpec.Validate call |
| 258 | err := s.FileSpec.UnmarshalSpec() |
| 259 | if err != nil { |
| 260 | return err |
| 261 | } |
| 262 | s.FileSpec.SetDefaults() |
| 263 | |
| 264 | return s.FileSpec.Validate() |
| 265 | } |
| 266 | |