pkg/firebase/bundleschema/bundleschema.go (82 lines of code) (raw):

// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Package bundleschema provides functionality around parsing and managing bundle.yaml. package bundleschema import ( "errors" "fmt" "os" "github.com/GoogleCloudPlatform/buildpacks/pkg/firebase/apphostingschema" "gopkg.in/yaml.v2" ) var ( validAvailabilityValues = map[string]bool{"RUNTIME": true} errMissingAdapterPackageName = errors.New("missing the adapter package name in bundle.yaml metadata") errMissingAdapterVersion = errors.New("missing the adapter version in bundle.yaml metadata") errMissingFrameworkName = errors.New("missing the framework name in bundle.yaml metadata") errMissingFrameworkVersion = errors.New("missing the framework version in bundle.yaml metadata") ) // EnvironmentVariable is the struct representation of the environment variables from bundle.yaml. type EnvironmentVariable apphostingschema.EnvironmentVariable // BundleSchema is the struct representation of bundle.yaml. type BundleSchema struct { RunConfig RunConfig `yaml:"runConfig"` Metadata *Metadata `yaml:"metadata,omitempty"` } // RunConfig is the struct representation of the passed cloud run config. type RunConfig struct { EnvironmentVariables []EnvironmentVariable `yaml:"environmentVariables,omitempty"` CPU *float32 `yaml:"cpu"` MemoryMiB *int32 `yaml:"memoryMiB"` Concurrency *int32 `yaml:"concurrency"` MaxInstances *int32 `yaml:"maxInstances"` MinInstances *int32 `yaml:"minInstances"` VpcAccess *apphostingschema.VpcAccess `yaml:"vpcAccess"` } // Metadata is the struct representation of the metadata from bundle.yaml. type Metadata struct { AdapterPackageName string `yaml:"adapterPackageName"` AdapterVersion string `yaml:"adapterVersion"` Framework string `yaml:"framework"` // TODO: b/366036980 retrieve community adapter's framework version from buildpack FrameworkVersion string `yaml:"frameworkVersion"` } // UnmarshalYAML provides custom validation logic to validate bundle.yaml environment variables. func (ev *EnvironmentVariable) UnmarshalYAML(unmarshal func(any) error) error { type standardYAML EnvironmentVariable // Define an alias // Use alias and standard unmarshal to avoid recursive unmarshal on EnvironmentVariable fields if err := unmarshal((*standardYAML)(ev)); err != nil { return err } if ev.Value == "" || ev.Secret != "" { return fmt.Errorf("for bundle.yaml environment variable %q, 'value' is required and 'secret' should not be present", ev.Variable) } for _, val := range ev.Availability { if !validAvailabilityValues[val] { return fmt.Errorf("invalid value %s in 'availability'", val) } } return nil } // UnmarshalYAML provides custom validation logic to validate bundle.yaml metadata. func (md *Metadata) UnmarshalYAML(unmarshal func(any) error) error { type standardYAML Metadata // Define an alias // Use alias and standard unmarshal to avoid recursive unmarshal on Metadata fields if err := unmarshal((*standardYAML)(md)); err != nil { return err } if md.AdapterPackageName == "" { return errMissingAdapterPackageName } if md.AdapterVersion == "" { return errMissingAdapterVersion } if md.Framework == "" { return errMissingFrameworkName } if md.FrameworkVersion == "" { return errMissingFrameworkVersion } return nil } // ReadAndValidateFromFile converts the provided file into an BundleSchema. func ReadAndValidateFromFile(filePath string) (BundleSchema, error) { var b BundleSchema bundleBuffer, err := os.ReadFile(filePath) if os.IsNotExist(err) { return b, fmt.Errorf("missing output bundle config at %v", filePath) } else if err != nil { return b, fmt.Errorf("reading output bundle config at %v: %w", filePath, err) } if err = yaml.Unmarshal(bundleBuffer, &b); err != nil { return b, fmt.Errorf("unmarshalling apphosting config as YAML: %w", err) } return b, nil }