codegen + updated headers + refactoring after reviews

This commit is contained in:
Leïla MARABESE 2022-10-19 09:55:58 +02:00
parent 284e98288e
commit f7f89080c6
13 changed files with 376 additions and 151 deletions

View File

@ -26,6 +26,7 @@ import (
"strconv"
"strings"
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/upup/pkg/fi/utils"
@ -210,35 +211,40 @@ func (b *BootstrapScript) buildEnvironmentVariables(cluster *kops.Cluster) (map[
}
if cluster.Spec.GetCloudProvider() == kops.CloudProviderScaleway {
errList := []error(nil)
region, err := scw.ParseRegion(os.Getenv("SCW_DEFAULT_REGION"))
if err != nil {
return nil, fmt.Errorf("error parsing SCW_DEFAULT_REGION: %w", err)
errList = append(errList, fmt.Errorf("error parsing SCW_DEFAULT_REGION: %w", err))
}
env["SCW_DEFAULT_REGION"] = string(region)
zone, err := scw.ParseZone(os.Getenv("SCW_DEFAULT_ZONE"))
if err != nil {
return nil, fmt.Errorf("error parsing SCW_DEFAULT_ZONE: %w", err)
errList = append(errList, fmt.Errorf("error parsing SCW_DEFAULT_ZONE: %w", err))
}
env["SCW_DEFAULT_ZONE"] = string(zone)
// We make sure that the credentials env vars are defined
scwAccessKey := os.Getenv("SCW_ACCESS_KEY")
if scwAccessKey == "" {
return nil, fmt.Errorf("SCW_ACCESS_KEY has to be set as an environment variable")
errList = append(errList, fmt.Errorf("SCW_ACCESS_KEY has to be set as an environment variable"))
}
env["SCW_ACCESS_KEY"] = scwAccessKey
scwSecretKey := os.Getenv("SCW_SECRET_KEY")
if scwSecretKey == "" {
return nil, fmt.Errorf("SCW_SECRET_KEY has to be set as an environment variable")
errList = append(errList, fmt.Errorf("SCW_SECRET_KEY has to be set as an environment variable"))
}
env["SCW_SECRET_KEY"] = scwSecretKey
scwProjectID := os.Getenv("SCW_DEFAULT_PROJECT_ID")
if scwProjectID == "" {
return nil, fmt.Errorf("SCW_DEFAULT_PROJECT_ID has to be set as an environment variable")
errList = append(errList, fmt.Errorf("SCW_DEFAULT_PROJECT_ID has to be set as an environment variable"))
}
// In theory all these variables will have been checked in NewScwCloud already
if len(errList) != 0 {
return nil, errors.NewAggregate(errList)
}
env["SCW_DEFAULT_REGION"] = string(region)
env["SCW_DEFAULT_ZONE"] = string(zone)
env["SCW_ACCESS_KEY"] = scwAccessKey
env["SCW_SECRET_KEY"] = scwSecretKey
env["SCW_DEFAULT_PROJECT_ID"] = scwProjectID
}

View File

@ -1,3 +1,19 @@
/*
Copyright 2022 The Kubernetes Authors.
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 scalewaymodel
import (

View File

@ -1,3 +1,19 @@
/*
Copyright 2022 The Kubernetes Authors.
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 scalewaymodel
import (

View File

@ -1,3 +1,19 @@
/*
Copyright 2022 The Kubernetes Authors.
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 scalewaymodel
import (

View File

@ -1,3 +1,3 @@
# See the OWNERS docs at https://go.k8s.io/owners
labels:
- area/provider/scaleway
- area/provider/scaleway

View File

@ -1,3 +1,19 @@
/*
Copyright 2022 The Kubernetes Authors.
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 scaleway
import "k8s.io/kops/upup/pkg/fi"

View File

@ -25,6 +25,7 @@ import (
"github.com/scaleway/scaleway-sdk-go/api/instance/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/klog/v2"
kopsv "k8s.io/kops"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
@ -44,23 +45,23 @@ const (
type ScwCloud interface {
fi.Cloud
ClusterName(tags []string) string
DNS() (dnsprovider.Interface, error)
ProviderID() kops.CloudProviderID
Region() string
Zone() string
ProviderID() kops.CloudProviderID
DNS() (dnsprovider.Interface, error)
ClusterName(tags []string) string
AccountService() *account.API
InstanceService() *instance.API
GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error)
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
GetCloudGroups(cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error)
DeleteGroup(group *cloudinstances.CloudInstanceGroup) error
FindVPCInfo(id string) (*fi.VPCInfo, error)
DetachInstance(instance *cloudinstances.CloudInstance) error
DeregisterInstance(instance *cloudinstances.CloudInstance) error
DeleteInstance(i *cloudinstances.CloudInstance) error
DeregisterInstance(instance *cloudinstances.CloudInstance) error
DetachInstance(instance *cloudinstances.CloudInstance) error
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
FindVPCInfo(id string) (*fi.VPCInfo, error)
GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error)
GetCloudGroups(cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error)
GetClusterServers(clusterName string, serverName *string) ([]*instance.Server, error)
GetClusterVolumes(clusterName string) ([]*instance.Volume, error)
@ -86,31 +87,37 @@ type scwCloudImplementation struct {
// NewScwCloud returns a Cloud with a Scaleway Client using the env vars SCW_ACCESS_KEY, SCW_SECRET_KEY,
// SCW_DEFAULT_PROJECT_ID, SCW_DEFAULT_REGION and SCW_DEFAULT_ZONE
func NewScwCloud(tags map[string]string) (ScwCloud, error) {
errList := []error(nil)
region, err := scw.ParseRegion(os.Getenv("SCW_DEFAULT_REGION"))
if err != nil {
return nil, fmt.Errorf("error parsing SCW_DEFAULT_REGION: %w", err)
errList = append(errList, fmt.Errorf("error parsing SCW_DEFAULT_REGION: %w", err))
}
zone, err := scw.ParseZone(os.Getenv("SCW_DEFAULT_ZONE"))
if err != nil {
return nil, fmt.Errorf("error parsing SCW_DEFAULT_ZONE: %w", err)
errList = append(errList, fmt.Errorf("error parsing SCW_DEFAULT_ZONE: %w", err))
}
// We make sure that the credentials env vars are defined
scwAccessKey := os.Getenv("SCW_ACCESS_KEY")
if scwAccessKey == "" {
return nil, fmt.Errorf("SCW_ACCESS_KEY has to be set as an environment variable")
errList = append(errList, fmt.Errorf("SCW_ACCESS_KEY has to be set as an environment variable"))
}
scwSecretKey := os.Getenv("SCW_SECRET_KEY")
if scwSecretKey == "" {
return nil, fmt.Errorf("SCW_SECRET_KEY has to be set as an environment variable")
errList = append(errList, fmt.Errorf("SCW_SECRET_KEY has to be set as an environment variable"))
}
scwProjectID := os.Getenv("SCW_DEFAULT_PROJECT_ID")
if scwProjectID == "" {
return nil, fmt.Errorf("SCW_DEFAULT_PROJECT_ID has to be set as an environment variable")
errList = append(errList, fmt.Errorf("SCW_DEFAULT_PROJECT_ID has to be set as an environment variable"))
}
if len(errList) != 0 {
return nil, errors.NewAggregate(errList)
}
scwClient, err := scw.NewClient(
scw.WithUserAgent("kubernetes-kops/"+kopsv.Version),
scw.WithUserAgent(KopsUserAgentPrefix+kopsv.Version),
scw.WithEnv(),
)
if err != nil {
@ -127,14 +134,6 @@ func NewScwCloud(tags map[string]string) (ScwCloud, error) {
}, nil
}
func (s *scwCloudImplementation) Region() string {
return string(s.region)
}
func (s *scwCloudImplementation) Zone() string {
return string(s.zone)
}
func (s *scwCloudImplementation) ClusterName(tags []string) string {
for _, tag := range tags {
if strings.HasPrefix(tag, TagClusterName) {
@ -144,13 +143,21 @@ func (s *scwCloudImplementation) ClusterName(tags []string) string {
return ""
}
func (s *scwCloudImplementation) DNS() (dnsprovider.Interface, error) {
klog.V(8).Infof("Scaleway DNS is not implemented yet")
return nil, fmt.Errorf("DNS is not implemented yet for Scaleway")
}
func (s *scwCloudImplementation) ProviderID() kops.CloudProviderID {
return kops.CloudProviderScaleway
}
func (s *scwCloudImplementation) DNS() (dnsprovider.Interface, error) {
//TODO(Mia-Cross) implement me
panic("Scaleway doesn't have a DNS yet")
func (s *scwCloudImplementation) Region() string {
return string(s.region)
}
func (s *scwCloudImplementation) Zone() string {
return string(s.zone)
}
func (s *scwCloudImplementation) AccountService() *account.API {
@ -161,10 +168,15 @@ func (s *scwCloudImplementation) InstanceService() *instance.API {
return s.instanceAPI
}
// FindVPCInfo is not implemented yet, it's only here to satisfy the fi.Cloud interface
func (s *scwCloudImplementation) FindVPCInfo(id string) (*fi.VPCInfo, error) {
klog.V(8).Info("FindVPCInfo is not implemented yet for Scaleway")
return nil, fmt.Errorf("scaleway cloud provider does not support VPC at this time")
func (s *scwCloudImplementation) DeleteGroup(group *cloudinstances.CloudInstanceGroup) error {
toDelete := append(group.NeedUpdate, group.Ready...)
for _, cloudInstance := range toDelete {
err := s.DeleteInstance(cloudInstance)
if err != nil {
return fmt.Errorf("error deleting group %q: %w", group.HumanName, err)
}
}
return nil
}
func (s *scwCloudImplementation) DeleteInstance(i *cloudinstances.CloudInstance) error {
@ -189,24 +201,30 @@ func (s *scwCloudImplementation) DeleteInstance(i *cloudinstances.CloudInstance)
}
func (s *scwCloudImplementation) DeregisterInstance(i *cloudinstances.CloudInstance) error {
//TODO(Mia-Cross) implement me
panic("implement me")
}
func (s *scwCloudImplementation) DeleteGroup(group *cloudinstances.CloudInstanceGroup) error {
toDelete := append(group.NeedUpdate, group.Ready...)
for _, cloudInstance := range toDelete {
err := s.DeleteInstance(cloudInstance)
if err != nil {
return fmt.Errorf("error deleting group %q: %w", group.HumanName, err)
}
}
return nil
klog.V(8).Infof("Scaleway DeregisterInstance is not implemented yet")
return fmt.Errorf("DeregisterInstance is not implemented yet for Scaleway")
}
func (s *scwCloudImplementation) DetachInstance(i *cloudinstances.CloudInstance) error {
//TODO(Mia-Cross) implement me
panic("implement me")
klog.V(8).Infof("Scaleway DetachInstance is not implemented yet")
return fmt.Errorf("DetachInstance is not implemented yet for Scaleway")
}
// FindClusterStatus was used before etcd-manager to check the etcd cluster status and prevent unsupported changes.
func (s *scwCloudImplementation) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error) {
klog.V(8).Info("Scaleway FindClusterStatus is not implemented")
return nil, nil
}
// FindVPCInfo is not implemented yet, it's only here to satisfy the fi.Cloud interface
func (s *scwCloudImplementation) FindVPCInfo(id string) (*fi.VPCInfo, error) {
klog.V(8).Info("Scaleway doesn't have a VPC yet so FindVPCInfo is not implemented")
return nil, fmt.Errorf("FindVPCInfo is not implemented yet for Scaleway")
}
func (s *scwCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
klog.V(8).Info("Scaleway doesn't have load-balancers yet so GetApiIngressStatus is not implemented")
return nil, fmt.Errorf("GetApiIngressStatus is not implemented yet for Scaleway")
}
func (s *scwCloudImplementation) GetCloudGroups(cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error) {
@ -219,24 +237,18 @@ func (s *scwCloudImplementation) GetCloudGroups(cluster *kops.Cluster, instanceg
return nil, fmt.Errorf("failed to find server groups: %w", err)
}
for igName, serverGroup := range serverGroups {
var instanceGroup *kops.InstanceGroup
for _, ig := range instancegroups {
if igName == ig.Name {
instanceGroup = ig
break
}
}
if instanceGroup == nil {
for _, ig := range instancegroups {
serverGroup, ok := serverGroups[ig.Name]
if !ok {
if warnUnmatched {
klog.Warningf("Server group %q has no corresponding instance group", igName)
klog.Warningf("Server group %q has no corresponding instance group", ig.Name)
}
continue
}
groups[instanceGroup.Name], err = buildCloudGroup(instanceGroup, serverGroup, nodeMap)
groups[ig.Name], err = buildCloudGroup(ig, serverGroup, nodeMap)
if err != nil {
return nil, fmt.Errorf("failed to build cloud group for instance group %q: %w", instanceGroup.Name, err)
return nil, fmt.Errorf("failed to build cloud group for instance group %q: %w", ig.Name, err)
}
}
@ -295,16 +307,6 @@ func buildCloudGroup(ig *kops.InstanceGroup, sg []*instance.Server, nodeMap map[
return cloudInstanceGroup, nil
}
func (s *scwCloudImplementation) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error) {
klog.V(8).Info("FindClusterStatus is not implemented yet for Scaleway")
return nil, nil
}
func (s *scwCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
//TODO(Mia-Cross) implement me
panic("implement me")
}
func (s *scwCloudImplementation) GetClusterServers(clusterName string, serverName *string) ([]*instance.Server, error) {
request := &instance.ListServersRequest{
Zone: s.zone,
@ -372,14 +374,12 @@ func (s *scwCloudImplementation) DeleteServer(server *instance.Server) error {
if err != nil {
return fmt.Errorf("delete server %s: error deleting instance: %w", server.ID, err)
}
for {
_, err := s.instanceAPI.GetServer(&instance.GetServerRequest{
Zone: s.zone,
ServerID: server.ID,
})
if is404Error(err) {
break
}
_, err = s.instanceAPI.WaitForServer(&instance.WaitForServerRequest{
ServerID: server.ID,
Zone: s.zone,
})
if !is404Error(err) {
return fmt.Errorf("delete server %s: error waiting for instance after deletion: %w", server.ID, err)
}
// We delete the volumes that were attached to the server (including etcd volumes)
@ -404,5 +404,14 @@ func (s *scwCloudImplementation) DeleteVolume(volume *instance.Volume) error {
if err != nil {
return fmt.Errorf("failed to delete volume %s: %w", volume.ID, err)
}
_, err = s.instanceAPI.WaitForVolume(&instance.WaitForVolumeRequest{
VolumeID: volume.ID,
Zone: s.zone,
})
if !is404Error(err) {
return fmt.Errorf("delete server %s: error waiting for volume after deletion: %w", volume.ID, err)
}
return nil
}

View File

@ -1,3 +1,19 @@
/*
Copyright 2022 The Kubernetes Authors.
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 scaleway
import (

View File

@ -1,3 +1,3 @@
# See the OWNERS docs at https://go.k8s.io/owners
labels:
- area/provider/scaleway
- area/provider/scaleway

View File

@ -1,3 +1,19 @@
/*
Copyright 2022 The Kubernetes Authors.
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 scalewaytasks
import (
@ -59,59 +75,37 @@ func (s *Instance) Run(c *fi.Context) error {
return fi.DefaultDeltaRunMethod(s, c)
}
func (_ *Instance) RenderScw(c *fi.Context, a, e, changes *Instance) error {
func (_ *Instance) RenderScw(c *fi.Context, actual, expected, changes *Instance) error {
cloud := c.Cloud.(scaleway.ScwCloud)
instanceService := cloud.InstanceService()
zone := scw.Zone(fi.StringValue(e.Zone))
zone := scw.Zone(fi.StringValue(expected.Zone))
userData, err := fi.ResourceAsBytes(*e.UserData)
userData, err := fi.ResourceAsBytes(*expected.UserData)
if err != nil {
return fmt.Errorf("error rendering instances: %w", err)
}
var newInstanceCount int
if a == nil {
newInstanceCount = e.Count
} else {
expectedCount := e.Count
actualCount := a.Count
if expectedCount == actualCount {
newInstanceCount := expected.Count
if actual != nil {
if expected.Count == actual.Count {
return nil
}
if actualCount > expectedCount {
igInstances, err := cloud.GetClusterServers(cloud.ClusterName(a.Tags), a.Name)
if err != nil {
return fmt.Errorf("error deleting instance: %w", err)
}
for _, igInstance := range igInstances {
err = cloud.DeleteServer(igInstance)
if err != nil {
return fmt.Errorf("error deleting instance of group %s: %w", igInstance.Name, err)
}
actualCount--
if expectedCount == actualCount {
break
}
}
}
newInstanceCount = expectedCount - actualCount
newInstanceCount = expected.Count - actual.Count
}
// If newInstanceCount > 0, we need to create new instances for this group
for i := 0; i < newInstanceCount; i++ {
// We create the instance
srv, err := instanceService.CreateServer(&instance.CreateServerRequest{
Zone: zone,
Name: fi.StringValue(e.Name),
CommercialType: fi.StringValue(e.CommercialType),
Image: fi.StringValue(e.Image),
Tags: e.Tags,
Name: fi.StringValue(expected.Name),
CommercialType: fi.StringValue(expected.CommercialType),
Image: fi.StringValue(expected.Image),
Tags: expected.Tags,
})
if err != nil {
return fmt.Errorf("error creating instance of group %q: %w", fi.StringValue(e.Name), err)
return fmt.Errorf("error creating instance of group %q: %w", fi.StringValue(expected.Name), err)
}
// We wait for the instance to be ready
@ -120,7 +114,7 @@ func (_ *Instance) RenderScw(c *fi.Context, a, e, changes *Instance) error {
Zone: zone,
})
if err != nil {
return fmt.Errorf("error waiting for instance %s of group %q: %w", srv.Server.ID, fi.StringValue(e.Name), err)
return fmt.Errorf("error waiting for instance %s of group %q: %w", srv.Server.ID, fi.StringValue(expected.Name), err)
}
// We load the cloud-init script in the instance user data
@ -131,7 +125,7 @@ func (_ *Instance) RenderScw(c *fi.Context, a, e, changes *Instance) error {
Content: bytes.NewBuffer(userData),
})
if err != nil {
return fmt.Errorf("error setting 'cloud-init' in user-data for instance %s of group %q: %w", srv.Server.ID, fi.StringValue(e.Name), err)
return fmt.Errorf("error setting 'cloud-init' in user-data for instance %s of group %q: %w", srv.Server.ID, fi.StringValue(expected.Name), err)
}
// We start the instance
@ -141,7 +135,7 @@ func (_ *Instance) RenderScw(c *fi.Context, a, e, changes *Instance) error {
Action: instance.ServerActionPoweron,
})
if err != nil {
return fmt.Errorf("error powering on instance %s of group %q: %w", srv.Server.ID, fi.StringValue(e.Name), err)
return fmt.Errorf("error powering on instance %s of group %q: %w", srv.Server.ID, fi.StringValue(expected.Name), err)
}
// We wait for the instance to be ready
@ -150,15 +144,31 @@ func (_ *Instance) RenderScw(c *fi.Context, a, e, changes *Instance) error {
Zone: zone,
})
if err != nil {
return fmt.Errorf("error waiting for instance %s of group %q: %w", srv.Server.ID, fi.StringValue(e.Name), err)
return fmt.Errorf("error waiting for instance %s of group %q: %w", srv.Server.ID, fi.StringValue(expected.Name), err)
}
}
// If newInstanceCount < 0, we need to delete instances of this group
for i := 0; i > expected.Count; i-- {
igInstances, err := cloud.GetClusterServers(cloud.ClusterName(actual.Tags), actual.Name)
if err != nil {
return fmt.Errorf("error deleting instance: %w", err)
}
for _, igInstance := range igInstances {
err = cloud.DeleteServer(igInstance)
if err != nil {
return fmt.Errorf("error deleting instance of group %s: %w", igInstance.Name, err)
}
}
}
return nil
}
func (_ *Instance) CheckChanges(a, e, changes *Instance) error {
if a != nil {
func (_ *Instance) CheckChanges(actual, expected, changes *Instance) error {
if actual != nil {
if changes.Name != nil {
return fi.CannotChangeField("Name")
}
@ -172,16 +182,16 @@ func (_ *Instance) CheckChanges(a, e, changes *Instance) error {
return fi.CannotChangeField("Image")
}
} else {
if e.Name == nil {
if expected.Name == nil {
return fi.RequiredField("Name")
}
if e.Zone == nil {
if expected.Zone == nil {
return fi.RequiredField("Zone")
}
if e.CommercialType == nil {
if expected.CommercialType == nil {
return fi.RequiredField("CommercialType")
}
if e.Image == nil {
if expected.Image == nil {
return fi.RequiredField("Image")
}
}

View File

@ -0,0 +1,52 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
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.
*/
// Code generated by fitask. DO NOT EDIT.
package scalewaytasks
import (
"k8s.io/kops/upup/pkg/fi"
)
// Instance
var _ fi.HasLifecycle = &Instance{}
// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *Instance) GetLifecycle() fi.Lifecycle {
return o.Lifecycle
}
// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *Instance) SetLifecycle(lifecycle fi.Lifecycle) {
o.Lifecycle = lifecycle
}
var _ fi.HasName = &Instance{}
// GetName returns the Name of the object, implementing fi.HasName
func (o *Instance) GetName() *string {
return o.Name
}
// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *Instance) String() string {
return fi.TaskAsString(o)
}

View File

@ -1,3 +1,19 @@
/*
Copyright 2022 The Kubernetes Authors.
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 scalewaytasks
import (
@ -46,25 +62,25 @@ func (s *SSHKey) Find(c *fi.Context) (*SSHKey, error) {
klog.V(2).Infof("found matching SSH key named %q", *s.Name)
k := keysResp.SSHKeys[0]
actual := &SSHKey{
sshKey := &SSHKey{
ID: fi.String(k.ID),
Name: fi.String(k.Name),
KeyPairFingerPrint: fi.String(k.Fingerprint),
}
// Avoid spurious changes
if strings.Contains(fi.StringValue(actual.KeyPairFingerPrint), fi.StringValue(s.KeyPairFingerPrint)) {
if strings.Contains(fi.StringValue(sshKey.KeyPairFingerPrint), fi.StringValue(s.KeyPairFingerPrint)) {
klog.V(2).Infof("SSH key fingerprints match; assuming public keys match")
actual.PublicKey = s.PublicKey
actual.KeyPairFingerPrint = s.KeyPairFingerPrint
sshKey.PublicKey = s.PublicKey
sshKey.KeyPairFingerPrint = s.KeyPairFingerPrint
} else {
klog.V(2).Infof("Computed SSH key fingerprint mismatch: %q %q", fi.StringValue(s.KeyPairFingerPrint), fi.StringValue(actual.KeyPairFingerPrint))
klog.V(2).Infof("Computed SSH key fingerprint mismatch: %q %q", fi.StringValue(s.KeyPairFingerPrint), fi.StringValue(sshKey.KeyPairFingerPrint))
}
// Ignore "system" fields
actual.Lifecycle = s.Lifecycle
sshKey.Lifecycle = s.Lifecycle
return actual, nil
return sshKey, nil
}
func (s *SSHKey) Run(c *fi.Context) error {
@ -84,8 +100,8 @@ func (s *SSHKey) Run(c *fi.Context) error {
return fi.DefaultDeltaRunMethod(s, c)
}
func (s *SSHKey) CheckChanges(a, e, changes *SSHKey) error {
if a != nil {
func (s *SSHKey) CheckChanges(actual, expected, changes *SSHKey) error {
if actual != nil {
if changes.Name != nil {
return fi.CannotChangeField("Name")
}
@ -93,12 +109,12 @@ func (s *SSHKey) CheckChanges(a, e, changes *SSHKey) error {
return nil
}
func (*SSHKey) RenderScw(c *fi.Context, a, e, changes *SSHKey) error {
func (*SSHKey) RenderScw(c *fi.Context, actual, expected, changes *SSHKey) error {
cloud := c.Cloud.(scaleway.ScwCloud)
if a == nil {
if actual == nil {
name := fi.StringValue(e.Name)
name := fi.StringValue(expected.Name)
if name == "" {
return fi.RequiredField("Name")
}
@ -107,8 +123,8 @@ func (*SSHKey) RenderScw(c *fi.Context, a, e, changes *SSHKey) error {
keyArgs := &account.CreateSSHKeyRequest{
Name: name,
}
if e.PublicKey != nil {
d, err := fi.ResourceAsString(*e.PublicKey)
if expected.PublicKey != nil {
d, err := fi.ResourceAsString(*expected.PublicKey)
if err != nil {
return fmt.Errorf("error rendering SSH public key: %w", err)
}
@ -119,14 +135,14 @@ func (*SSHKey) RenderScw(c *fi.Context, a, e, changes *SSHKey) error {
if err != nil {
return fmt.Errorf("error creating SSH keypair: %w", err)
}
e.KeyPairFingerPrint = fi.String(key.Fingerprint)
expected.KeyPairFingerPrint = fi.String(key.Fingerprint)
klog.V(2).Infof("Created a new SSH keypair, id=%q fingerprint=%q", key.ID, key.Fingerprint)
return nil
}
e.KeyPairFingerPrint = a.KeyPairFingerPrint
klog.V(2).Infof("Using an existing SSH keypair, fingerprint=%q", fi.StringValue(e.KeyPairFingerPrint))
expected.KeyPairFingerPrint = actual.KeyPairFingerPrint
klog.V(2).Infof("Using an existing SSH keypair, fingerprint=%q", fi.StringValue(expected.KeyPairFingerPrint))
return nil
}

View File

@ -0,0 +1,52 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
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.
*/
// Code generated by fitask. DO NOT EDIT.
package scalewaytasks
import (
"k8s.io/kops/upup/pkg/fi"
)
// SSHKey
var _ fi.HasLifecycle = &SSHKey{}
// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *SSHKey) GetLifecycle() fi.Lifecycle {
return o.Lifecycle
}
// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *SSHKey) SetLifecycle(lifecycle fi.Lifecycle) {
o.Lifecycle = lifecycle
}
var _ fi.HasName = &SSHKey{}
// GetName returns the Name of the object, implementing fi.HasName
func (o *SSHKey) GetName() *string {
return o.Name
}
// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *SSHKey) String() string {
return fi.TaskAsString(o)
}