code/go/internal/validator/semantic/validate_ilmpolicypresent.go (83 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. package semantic import ( "fmt" "io/fs" "path" "strings" "gopkg.in/yaml.v3" "github.com/elastic/package-spec/v3/code/go/internal/fspath" "github.com/elastic/package-spec/v3/code/go/pkg/specerrors" ) // ValidateILMPolicyPresent produces an error if the indicated ILM policy // is not defined in the data stream. func ValidateILMPolicyPresent(fsys fspath.FS) specerrors.ValidationErrors { dataStreams, err := listDataStreams(fsys) if err != nil { return specerrors.ValidationErrors{specerrors.NewStructuredError(err, specerrors.UnassignedCode)} } var errs specerrors.ValidationErrors for _, dataStream := range dataStreams { err = validateILMPolicyInDataStream(fsys, dataStream) if err != nil { errs = append(errs, specerrors.NewStructuredError(err, specerrors.UnassignedCode)) } } return errs } func validateILMPolicyInDataStream(fsys fspath.FS, dataStream string) error { dsType, ilmPolicy, err := readILMPolicyInfoInDataStream(fsys, dataStream) if err != nil { return err } if ilmPolicy == "" { return nil } packageName, err := readPackageName(fsys) if err != nil { return err } manifestPath := path.Join("data_stream", dataStream, "manifest.yml") policyPrefix := expectedILMPolicyPrefix(dsType, packageName, dataStream) if !strings.HasPrefix(ilmPolicy, policyPrefix) { return fmt.Errorf("file \"%s\" is invalid: field ilm_policy must start with %q, found \"%s\"", fsys.Path(manifestPath), policyPrefix, ilmPolicy) } ilmFileName := ilmPolicy[len(policyPrefix):] + ".json" ilmFilePath := path.Join("data_stream", dataStream, "elasticsearch", "ilm", ilmFileName) _, err = fs.Stat(fsys, ilmFilePath) if err != nil { return fmt.Errorf("file \"%s\" is invalid: field ilm_policy: ILM policy %q not found in package, expected definition in \"%s\"", fsys.Path(manifestPath), ilmPolicy, fsys.Path(ilmFilePath)) } return nil } func readILMPolicyInfoInDataStream(fsys fspath.FS, dataStream string) (dsType string, ilmPolicy string, err error) { manifestPath := path.Join("data_stream", dataStream, "manifest.yml") d, err := fs.ReadFile(fsys, manifestPath) if err != nil { return "", "", fmt.Errorf("failed to read data stream manifest in %q: %w", fsys.Path(manifestPath), err) } var manifest struct { Type string `yaml:"type"` ILMPolicy string `yaml:"ilm_policy"` } err = yaml.Unmarshal(d, &manifest) if err != nil { return "", "", fmt.Errorf("failed to parse data stream manifest in %q: %w", fsys.Path(manifestPath), err) } return manifest.Type, manifest.ILMPolicy, nil } func readPackageName(fsys fspath.FS) (string, error) { manifestPath := "manifest.yml" d, err := fs.ReadFile(fsys, manifestPath) if err != nil { return "", fmt.Errorf("failed to manifest in %q: %w", fsys.Path(manifestPath), err) } var manifest struct { Name string `yaml:"name"` } err = yaml.Unmarshal(d, &manifest) if err != nil { return "", fmt.Errorf("failed to parse manifest in %q: %w", fsys.Path(manifestPath), err) } return manifest.Name, nil } func expectedILMPolicyPrefix(dsType, packageName, dataStream string) string { return fmt.Sprintf("%s-%s.%s-", dsType, packageName, dataStream) }