github.com/munnerz/test-infra@v0.0.0-20190108210205-ce3d181dc989/boskos/mason/storage.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package mason
    18  
    19  import (
    20  	"reflect"
    21  	"sync"
    22  
    23  	"github.com/deckarep/golang-set"
    24  	"github.com/hashicorp/go-multierror"
    25  	"github.com/sirupsen/logrus"
    26  	"k8s.io/test-infra/boskos/common"
    27  	"k8s.io/test-infra/boskos/storage"
    28  )
    29  
    30  // Storage stores configuration information
    31  type Storage struct {
    32  	configs     storage.PersistenceLayer
    33  	configsLock sync.RWMutex
    34  }
    35  
    36  func newStorage(c storage.PersistenceLayer) *Storage {
    37  	return &Storage{
    38  		configs: c,
    39  	}
    40  }
    41  
    42  // AddConfig adds a new config
    43  func (s *Storage) AddConfig(conf common.ResourcesConfig) error {
    44  	return s.configs.Add(conf)
    45  }
    46  
    47  // DeleteConfig deletes an existing config if it exists or fail otherwise
    48  func (s *Storage) DeleteConfig(name string) error {
    49  	return s.configs.Delete(name)
    50  }
    51  
    52  // UpdateConfig updates a given if it exists or fail otherwise
    53  func (s *Storage) UpdateConfig(conf common.ResourcesConfig) error {
    54  	return s.configs.Update(conf)
    55  }
    56  
    57  // GetConfig returns an existing if it exists errors out otherwise
    58  func (s *Storage) GetConfig(name string) (common.ResourcesConfig, error) {
    59  	i, err := s.configs.Get(name)
    60  	if err != nil {
    61  		return common.ResourcesConfig{}, err
    62  	}
    63  	var conf common.ResourcesConfig
    64  	conf, err = common.ItemToResourcesConfig(i)
    65  	if err != nil {
    66  		return common.ResourcesConfig{}, err
    67  	}
    68  	return conf, nil
    69  }
    70  
    71  // GetConfigs returns all configs
    72  func (s *Storage) GetConfigs() ([]common.ResourcesConfig, error) {
    73  	var configs []common.ResourcesConfig
    74  	items, err := s.configs.List()
    75  	if err != nil {
    76  		return configs, err
    77  	}
    78  	for _, i := range items {
    79  		var conf common.ResourcesConfig
    80  		conf, err = common.ItemToResourcesConfig(i)
    81  		if err != nil {
    82  			return nil, err
    83  		}
    84  		configs = append(configs, conf)
    85  	}
    86  	return configs, nil
    87  }
    88  
    89  // SyncConfigs syncs new configs
    90  func (s *Storage) SyncConfigs(newConfigs []common.ResourcesConfig) error {
    91  	s.configsLock.Lock()
    92  	defer s.configsLock.Unlock()
    93  
    94  	currentConfigs, err := s.GetConfigs()
    95  	if err != nil {
    96  		logrus.WithError(err).Error("cannot find configs")
    97  		return err
    98  	}
    99  
   100  	currentSet := mapset.NewSet()
   101  	newSet := mapset.NewSet()
   102  	toUpdate := mapset.NewSet()
   103  
   104  	configs := map[string]common.ResourcesConfig{}
   105  
   106  	for _, c := range currentConfigs {
   107  		currentSet.Add(c.Name)
   108  		configs[c.Name] = c
   109  	}
   110  
   111  	for _, c := range newConfigs {
   112  		newSet.Add(c.Name)
   113  		if old, exists := configs[c.Name]; exists {
   114  			if !reflect.DeepEqual(old, c) {
   115  				toUpdate.Add(c.Name)
   116  				configs[c.Name] = c
   117  			}
   118  		} else {
   119  			configs[c.Name] = c
   120  		}
   121  	}
   122  
   123  	var finalError error
   124  
   125  	toDelete := currentSet.Difference(newSet)
   126  	toAdd := newSet.Difference(currentSet)
   127  
   128  	for _, n := range toDelete.ToSlice() {
   129  		logrus.Infof("Deleting config %s", n.(string))
   130  		if err := s.DeleteConfig(n.(string)); err != nil {
   131  			logrus.WithError(err).Errorf("failed to delete config %s", n)
   132  			finalError = multierror.Append(finalError, err)
   133  		}
   134  	}
   135  
   136  	for _, n := range toAdd.ToSlice() {
   137  		rc := configs[n.(string)]
   138  		logrus.Infof("Adding config %s", n.(string))
   139  		if err := s.AddConfig(rc); err != nil {
   140  			logrus.WithError(err).Errorf("failed to create resources %s", n)
   141  			finalError = multierror.Append(finalError, err)
   142  		}
   143  	}
   144  
   145  	for _, n := range toUpdate.ToSlice() {
   146  		rc := configs[n.(string)]
   147  		logrus.Infof("Updating config %s", n.(string))
   148  		if err := s.UpdateConfig(rc); err != nil {
   149  			logrus.WithError(err).Errorf("failed to update resources %s", n)
   150  			finalError = multierror.Append(finalError, err)
   151  		}
   152  	}
   153  
   154  	return finalError
   155  }