blob: 498882be2a38f15a7cf73b0b51a70df1817ad67e [file] [log] [blame]
// Copyright 2018 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 config exports functionality for storing/retrieving build step configuration on/from
// the local disk.
package config
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"cos.googlesource.com/cos/tools.git/src/pkg/utils"
compute "google.golang.org/api/compute/v1"
)
// Image stores GCE image configuration.
type Image struct {
*compute.Image
Project string
}
// NewImage builds an Image with some initialized defaults.
func NewImage(name string, project string) *Image {
return &Image{
&compute.Image{Name: name, Labels: make(map[string]string)},
project,
}
}
// URL gets the partial GCE URL of the image.
func (i *Image) URL() string {
return fmt.Sprintf("projects/%s/global/images/%s", i.Project, i.Name)
}
// MarshalJSON marshals the image configuration into JSON.
func (i *Image) MarshalJSON() ([]byte, error) {
computeImData, err := json.Marshal(i.Image)
if err != nil {
return nil, err
}
computeIm := make(map[string]interface{})
if err := json.Unmarshal(computeImData, &computeIm); err != nil {
return nil, err
}
computeIm["Project"] = i.Project
return json.Marshal(computeIm)
}
// Build stores configuration data associated with the image build session.
type Build struct {
GCSBucket string
GCSDir string
Project string
Zone string
MachineType string
DiskSize int
GPUType string
Timeout string
GCSFiles []string
GCEEndpoint string
}
// SaveConfigToFile clears the target config file and then saves the new config
// data.
func SaveConfigToFile(configFile *os.File, v interface{}) error {
if _, err := configFile.Seek(0, 0); err != nil {
return fmt.Errorf("cannot seek config file, error msg:(%v)", err)
}
if err := configFile.Truncate(0); err != nil {
return fmt.Errorf("cannot truncate config file, error msg:(%v)", err)
}
if err := Save(configFile, v); err != nil {
return fmt.Errorf("cannot save config file, error msg:(%v)", err)
}
return nil
}
// SaveConfigToPath does the same thing as SaveConfigToFile, but updates a file
// system path.
func SaveConfigToPath(configPath string, config interface{}) (err error) {
configFile, err := os.OpenFile(configPath, os.O_RDWR, 0666)
if err != nil {
return err
}
defer utils.CheckClose(configFile, "error writing to "+configPath, &err)
return SaveConfigToFile(configFile, config)
}
// Save serializes the given struct as JSON and writes it out.
func Save(w io.Writer, v interface{}) error {
data, err := json.Marshal(v)
if err != nil {
return err
}
_, err = io.WriteString(w, string(data))
return err
}
// Load deserializes JSON formatted data into the given struct.
func Load(r io.Reader, v interface{}) error {
data, err := ioutil.ReadAll(r)
if err != nil {
return err
}
return json.Unmarshal(data, v)
}
// LoadFromFile loads JSON data from a file into the given struct.
func LoadFromFile(path string, v interface{}) (err error) {
r, err := os.Open(path)
if err != nil {
return err
}
defer utils.CheckClose(r, fmt.Sprintf("error closing %q", path), &err)
return Load(r, v)
}