diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e76aa23..9b2a5af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ on: env: # Common versions - GO_VERSION: '1.21' + GO_VERSION: '1.22' GOLANGCI_VERSION: 'v1.54.2' DOCKER_BUILDX_VERSION: 'v0.8.2' @@ -70,7 +70,7 @@ jobs: restore-keys: ${{ runner.os }}-build-lint- - name: Vendor Dependencies - run: make vendor vendor.check + run: make go.vendor go.vendor.check # We could run 'make lint' but we prefer this action because it leaves # 'annotations' (i.e. it comments on PRs to point out linter violations). @@ -112,7 +112,7 @@ jobs: restore-keys: ${{ runner.os }}-build-check-diff- - name: Vendor Dependencies - run: make vendor vendor.check + run: make go.vendor go.vendor.check - name: Check Diff id: check-diff @@ -154,7 +154,7 @@ jobs: restore-keys: ${{ runner.os }}-build-unit-tests- - name: Vendor Dependencies - run: make vendor vendor.check + run: make go.vendor go.vendor.check - name: Run Unit Tests run: make -j2 test @@ -193,7 +193,7 @@ jobs: restore-keys: ${{ runner.os }}-build-local-deploy- - name: Vendor Dependencies - run: make vendor vendor.check + run: make go.vendor go.vendor.check - name: Deploying locally built provider package run: make local-deploy @@ -248,7 +248,7 @@ jobs: restore-keys: ${{ runner.os }}-build-publish-artifacts- - name: Vendor Dependencies - run: make vendor vendor.check + run: make go.vendor go.vendor.check - name: Build Artifacts run: make -j2 build.all diff --git a/.gitmodules b/.gitmodules index c2fad47..8f84209 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "build"] path = build - url = https://github.com/upbound/build + url = https://github.com/crossplane/build diff --git a/Makefile b/Makefile index 4c6b6fc..cdb7e6c 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ export TERRAFORM_PROVIDER_DOWNLOAD_NAME := terraform-provider-linode export TERRAFORM_NATIVE_PROVIDER_BINARY := terraform-provider-linode_v$(TERRAFORM_PROVIDER_VERSION) export TERRAFORM_PROVIDER_REPO := https://github.com/linode/terraform-provider-linode export TERRAFORM_DOCS_PATH := docs/resources +export CROSSPLANE_VERSION := 1.16 PLATFORMS ?= linux_amd64 linux_arm64 diff --git a/apis/firewall/v1alpha1/zz_generated.conversion_hubs.go b/apis/firewall/v1alpha1/zz_generated.conversion_hubs.go index deec4ac..4c16616 100755 --- a/apis/firewall/v1alpha1/zz_generated.conversion_hubs.go +++ b/apis/firewall/v1alpha1/zz_generated.conversion_hubs.go @@ -7,7 +7,7 @@ Copyright 2022 Upbound Inc. package v1alpha1 // Hub marks this type as a conversion hub. -func (tr *Firewall) Hub() {} +func (tr *Device) Hub() {} // Hub marks this type as a conversion hub. -func (tr *Device) Hub() {} +func (tr *Firewall) Hub() {} diff --git a/apis/instance/v1alpha1/zz_disk_terraformed.go b/apis/instance/v1alpha1/zz_disk_terraformed.go index 5959f5c..f0e724d 100755 --- a/apis/instance/v1alpha1/zz_disk_terraformed.go +++ b/apis/instance/v1alpha1/zz_disk_terraformed.go @@ -21,7 +21,7 @@ func (mg *Disk) GetTerraformResourceType() string { // GetConnectionDetailsMapping for this Disk func (tr *Disk) GetConnectionDetailsMapping() map[string]string { - return map[string]string{"root_pass": "spec.forProvider.rootPassSecretRef", "stackscript_data": "spec.forProvider.stackscriptDataSecretRef"} + return map[string]string{"root_pass": "rootPassSecretRef", "stackscript_data": "stackscriptDataSecretRef"} } // GetObservation of this Disk diff --git a/apis/instance/v1alpha1/zz_disk_types.go b/apis/instance/v1alpha1/zz_disk_types.go index fc36440..c6a099f 100755 --- a/apis/instance/v1alpha1/zz_disk_types.go +++ b/apis/instance/v1alpha1/zz_disk_types.go @@ -50,10 +50,16 @@ type DiskInitParameters_2 struct { // +kubebuilder:validation:Optional LinodeIDSelector *v1.Selector `json:"linodeIdSelector,omitempty" tf:"-"` + // The root user’s password on a newly-created Linode Disk when deploying from an Image. (Requires image) + // This sets the root user's password on a newly-created Linode Disk when deploying from an Image. + RootPassSecretRef *v1.SecretKeySelector `json:"rootPassSecretRef,omitempty" tf:"-"` + // The size of the Disk in MB. NOTE: Resizing a disk will trigger a Linode reboot. // The ID of the token. Size *float64 `json:"size,omitempty" tf:"size,omitempty"` + StackscriptData map[string]*string `json:"stackscriptDataSecretRef,omitempty" tf:"-"` + // A StackScript ID that will cause the referenced StackScript to be run during deployment of this Disk. (Requires image) // A StackScript ID that will cause the referenced StackScript to be run during deployment of this Linode. // +crossplane:generate:reference:type=github.com/linode/provider-linode/apis/stackscript/v1alpha1.Stackscript diff --git a/apis/instance/v1alpha1/zz_generated.conversion_hubs.go b/apis/instance/v1alpha1/zz_generated.conversion_hubs.go index d1a62c4..7444416 100755 --- a/apis/instance/v1alpha1/zz_generated.conversion_hubs.go +++ b/apis/instance/v1alpha1/zz_generated.conversion_hubs.go @@ -6,15 +6,15 @@ Copyright 2022 Upbound Inc. package v1alpha1 -// Hub marks this type as a conversion hub. -func (tr *Instance) Hub() {} - // Hub marks this type as a conversion hub. func (tr *Config) Hub() {} // Hub marks this type as a conversion hub. func (tr *Disk) Hub() {} +// Hub marks this type as a conversion hub. +func (tr *Instance) Hub() {} + // Hub marks this type as a conversion hub. func (tr *IP) Hub() {} diff --git a/apis/instance/v1alpha1/zz_generated.deepcopy.go b/apis/instance/v1alpha1/zz_generated.deepcopy.go index 956916a..820bacf 100644 --- a/apis/instance/v1alpha1/zz_generated.deepcopy.go +++ b/apis/instance/v1alpha1/zz_generated.deepcopy.go @@ -2528,11 +2528,32 @@ func (in *DiskInitParameters) DeepCopyInto(out *DiskInitParameters) { *out = new(bool) **out = **in } + if in.RootPassSecretRef != nil { + in, out := &in.RootPassSecretRef, &out.RootPassSecretRef + *out = new(v1.SecretKeySelector) + **out = **in + } if in.Size != nil { in, out := &in.Size, &out.Size *out = new(float64) **out = **in } + if in.StackscriptData != nil { + in, out := &in.StackscriptData, &out.StackscriptData + *out = make(map[string]*string, len(*in)) + for key, val := range *in { + var outVal *string + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(string) + **out = **in + } + (*out)[key] = outVal + } + } if in.StackscriptID != nil { in, out := &in.StackscriptID, &out.StackscriptID *out = new(float64) @@ -2605,11 +2626,32 @@ func (in *DiskInitParameters_2) DeepCopyInto(out *DiskInitParameters_2) { *out = new(v1.Selector) (*in).DeepCopyInto(*out) } + if in.RootPassSecretRef != nil { + in, out := &in.RootPassSecretRef, &out.RootPassSecretRef + *out = new(v1.SecretKeySelector) + **out = **in + } if in.Size != nil { in, out := &in.Size, &out.Size *out = new(float64) **out = **in } + if in.StackscriptData != nil { + in, out := &in.StackscriptData, &out.StackscriptData + *out = make(map[string]*string, len(*in)) + for key, val := range *in { + var outVal *string + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(string) + **out = **in + } + (*out)[key] = outVal + } + } if in.StackscriptID != nil { in, out := &in.StackscriptID, &out.StackscriptID *out = new(float64) @@ -3660,6 +3702,11 @@ func (in *InstanceInitParameters) DeepCopyInto(out *InstanceInitParameters) { *out = new(bool) **out = **in } + if in.RootPassSecretRef != nil { + in, out := &in.RootPassSecretRef, &out.RootPassSecretRef + *out = new(v1.SecretKeySelector) + **out = **in + } if in.SharedIPv4 != nil { in, out := &in.SharedIPv4, &out.SharedIPv4 *out = make([]*string, len(*in)) @@ -3671,6 +3718,22 @@ func (in *InstanceInitParameters) DeepCopyInto(out *InstanceInitParameters) { } } } + if in.StackscriptData != nil { + in, out := &in.StackscriptData, &out.StackscriptData + *out = make(map[string]*string, len(*in)) + for key, val := range *in { + var outVal *string + if val == nil { + (*out)[key] = nil + } else { + inVal := (*in)[key] + in, out := &inVal, &outVal + *out = new(string) + **out = **in + } + (*out)[key] = outVal + } + } if in.StackscriptID != nil { in, out := &in.StackscriptID, &out.StackscriptID *out = new(float64) diff --git a/apis/instance/v1alpha1/zz_instance_terraformed.go b/apis/instance/v1alpha1/zz_instance_terraformed.go index a61f5c0..137dd45 100755 --- a/apis/instance/v1alpha1/zz_instance_terraformed.go +++ b/apis/instance/v1alpha1/zz_instance_terraformed.go @@ -21,7 +21,7 @@ func (mg *Instance) GetTerraformResourceType() string { // GetConnectionDetailsMapping for this Instance func (tr *Instance) GetConnectionDetailsMapping() map[string]string { - return map[string]string{"disk[*].root_pass": "spec.forProvider.disk[*].rootPassSecretRef", "disk[*].stackscript_data": "spec.forProvider.disk[*].stackscriptDataSecretRef", "root_pass": "spec.forProvider.rootPassSecretRef", "stackscript_data": "spec.forProvider.stackscriptDataSecretRef"} + return map[string]string{"disk[*].root_pass": "disk[*].rootPassSecretRef", "disk[*].stackscript_data": "disk[*].stackscriptDataSecretRef", "root_pass": "rootPassSecretRef", "stackscript_data": "stackscriptDataSecretRef"} } // GetObservation of this Instance diff --git a/apis/instance/v1alpha1/zz_instance_types.go b/apis/instance/v1alpha1/zz_instance_types.go index 9300e5a..95ba39c 100755 --- a/apis/instance/v1alpha1/zz_instance_types.go +++ b/apis/instance/v1alpha1/zz_instance_types.go @@ -358,10 +358,16 @@ type DiskInitParameters struct { // If true, this Disk is read-only. ReadOnly *bool `json:"readOnly,omitempty" tf:"read_only,omitempty"` + // The initial password for the root user account. This value can not be imported. + // The password that will be initialially assigned to the 'root' user account. + RootPassSecretRef *v1.SecretKeySelector `json:"rootPassSecretRef,omitempty" tf:"-"` + // The size of the Disk in MB. // The size of the Disk in MB. Size *float64 `json:"size,omitempty" tf:"size,omitempty"` + StackscriptData map[string]*string `json:"stackscriptDataSecretRef,omitempty" tf:"-"` + // The StackScript to deploy to the newly created Linode. If provided, 'image' must also be provided, and must be an Image that is compatible with this StackScript. This value can not be imported. Changing // The StackScript to deploy to the newly created Linode. If provided, 'image' must also be provided, and must be an Image that is compatible with this StackScript. StackscriptID *float64 `json:"stackscriptId,omitempty" tf:"stackscript_id,omitempty"` @@ -634,11 +640,17 @@ type InstanceInitParameters struct { // If true, changes in Linode type will attempt to upsize or downsize implicitly created disks. This must be false if explicit disks are defined. This is an irreversible action as Linode disks cannot be automatically downsized. ResizeDisk *bool `json:"resizeDisk,omitempty" tf:"resize_disk,omitempty"` + // The initial password for the root user account. This value can not be imported. + // The password that will be initially assigned to the 'root' user account. + RootPassSecretRef *v1.SecretKeySelector `json:"rootPassSecretRef,omitempty" tf:"-"` + // A set of IPv4 addresses to be shared with the Instance. These IP addresses can be both private and public, but must be in the same region as the instance. // A set of IPv4 addresses to share with this Linode. // +listType=set SharedIPv4 []*string `json:"sharedIpv4,omitempty" tf:"shared_ipv4,omitempty"` + StackscriptData map[string]*string `json:"stackscriptDataSecretRef,omitempty" tf:"-"` + // The StackScript to deploy to the newly created Linode. If provided, 'image' must also be provided, and must be an Image that is compatible with this StackScript. This value can not be imported. Changing // The StackScript to deploy to the newly created Linode. If provided, 'image' must also be provided, and must be an Image that is compatible with this StackScript. // +crossplane:generate:reference:type=github.com/linode/provider-linode/apis/stackscript/v1alpha1.Stackscript diff --git a/apis/nodebalancer/v1alpha1/zz_config_terraformed.go b/apis/nodebalancer/v1alpha1/zz_config_terraformed.go index d304a4f..0b76c63 100755 --- a/apis/nodebalancer/v1alpha1/zz_config_terraformed.go +++ b/apis/nodebalancer/v1alpha1/zz_config_terraformed.go @@ -21,7 +21,7 @@ func (mg *Config) GetTerraformResourceType() string { // GetConnectionDetailsMapping for this Config func (tr *Config) GetConnectionDetailsMapping() map[string]string { - return map[string]string{"ssl_cert": "spec.forProvider.sslCertSecretRef", "ssl_key": "spec.forProvider.sslKeySecretRef"} + return map[string]string{"ssl_cert": "sslCertSecretRef", "ssl_key": "sslKeySecretRef"} } // GetObservation of this Config diff --git a/apis/nodebalancer/v1alpha1/zz_config_types.go b/apis/nodebalancer/v1alpha1/zz_config_types.go index 54fac05..c63caa7 100755 --- a/apis/nodebalancer/v1alpha1/zz_config_types.go +++ b/apis/nodebalancer/v1alpha1/zz_config_types.go @@ -75,6 +75,14 @@ type ConfigInitParameters struct { // The version of ProxyProtocol to use for the underlying NodeBalancer. This requires protocol to be `tcp`. Valid values are `none`, `v1`, and `v2`. ProxyProtocol *string `json:"proxyProtocol,omitempty" tf:"proxy_protocol,omitempty"` + // The certificate this port is serving. This is not returned. If set, this field will come back as . Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + // The certificate this port is serving. This is not returned. If set, this field will come back as ``. Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + SSLCertSecretRef *v1.SecretKeySelector `json:"sslCertSecretRef,omitempty" tf:"-"` + + // The private key corresponding to this port's certificate. This is not returned. If set, this field will come back as . Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + // The private key corresponding to this port's certificate. This is not returned. If set, this field will come back as ``. Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + SSLKeySecretRef *v1.SecretKeySelector `json:"sslKeySecretRef,omitempty" tf:"-"` + // Controls how session stickiness is handled on this port. (none, table, http_cookie) // Controls how session stickiness is handled on this port: 'none', 'table', 'http_cookie' Stickiness *string `json:"stickiness,omitempty" tf:"stickiness,omitempty"` diff --git a/apis/nodebalancer/v1alpha1/zz_generated.conversion_hubs.go b/apis/nodebalancer/v1alpha1/zz_generated.conversion_hubs.go index c946907..8bbf848 100755 --- a/apis/nodebalancer/v1alpha1/zz_generated.conversion_hubs.go +++ b/apis/nodebalancer/v1alpha1/zz_generated.conversion_hubs.go @@ -6,11 +6,11 @@ Copyright 2022 Upbound Inc. package v1alpha1 -// Hub marks this type as a conversion hub. -func (tr *Nodebalancer) Hub() {} - // Hub marks this type as a conversion hub. func (tr *Config) Hub() {} // Hub marks this type as a conversion hub. func (tr *Node) Hub() {} + +// Hub marks this type as a conversion hub. +func (tr *Nodebalancer) Hub() {} diff --git a/apis/nodebalancer/v1alpha1/zz_generated.deepcopy.go b/apis/nodebalancer/v1alpha1/zz_generated.deepcopy.go index 58306f0..9d5924e 100644 --- a/apis/nodebalancer/v1alpha1/zz_generated.deepcopy.go +++ b/apis/nodebalancer/v1alpha1/zz_generated.deepcopy.go @@ -118,6 +118,16 @@ func (in *ConfigInitParameters) DeepCopyInto(out *ConfigInitParameters) { *out = new(string) **out = **in } + if in.SSLCertSecretRef != nil { + in, out := &in.SSLCertSecretRef, &out.SSLCertSecretRef + *out = new(v1.SecretKeySelector) + **out = **in + } + if in.SSLKeySecretRef != nil { + in, out := &in.SSLKeySecretRef, &out.SSLKeySecretRef + *out = new(v1.SecretKeySelector) + **out = **in + } if in.Stickiness != nil { in, out := &in.Stickiness, &out.Stickiness *out = new(string) diff --git a/apis/objectstorage/v1alpha1/zz_bucket_terraformed.go b/apis/objectstorage/v1alpha1/zz_bucket_terraformed.go index 9cdae21..3c0fdd1 100755 --- a/apis/objectstorage/v1alpha1/zz_bucket_terraformed.go +++ b/apis/objectstorage/v1alpha1/zz_bucket_terraformed.go @@ -21,7 +21,7 @@ func (mg *Bucket) GetTerraformResourceType() string { // GetConnectionDetailsMapping for this Bucket func (tr *Bucket) GetConnectionDetailsMapping() map[string]string { - return map[string]string{"secret_key": "spec.forProvider.secretKeySecretRef"} + return map[string]string{"secret_key": "secretKeySecretRef"} } // GetObservation of this Bucket diff --git a/apis/objectstorage/v1alpha1/zz_bucket_types.go b/apis/objectstorage/v1alpha1/zz_bucket_types.go index 7f7ccd3..442f3dd 100755 --- a/apis/objectstorage/v1alpha1/zz_bucket_types.go +++ b/apis/objectstorage/v1alpha1/zz_bucket_types.go @@ -52,6 +52,10 @@ type BucketInitParameters struct { // Lifecycle rules to be applied to the bucket. LifecycleRule []LifecycleRuleInitParameters `json:"lifecycleRule,omitempty" tf:"lifecycle_rule,omitempty"` + // The secret key to authenticate with. If not specified with the resource, its value can be + // The S3 secret key to use for this resource. (Required for lifecycle_rule and versioning). If not specified with the resource, the value will be read from provider-level obj_secret_key, or, generated implicitly at apply-time if obj_use_temp_keys in provider configuration is set. + SecretKeySecretRef *v1.SecretKeySelector `json:"secretKeySecretRef,omitempty" tf:"-"` + // Whether to enable versioning. Once you version-enable a bucket, it can never return to an unversioned state. You can, however, suspend versioning on that bucket. (Requires access_key and secret_key) // Whether to enable versioning. Versioning *bool `json:"versioning,omitempty" tf:"versioning,omitempty"` diff --git a/apis/objectstorage/v1alpha1/zz_generated.deepcopy.go b/apis/objectstorage/v1alpha1/zz_generated.deepcopy.go index 880b9f3..08c5897 100644 --- a/apis/objectstorage/v1alpha1/zz_generated.deepcopy.go +++ b/apis/objectstorage/v1alpha1/zz_generated.deepcopy.go @@ -182,6 +182,11 @@ func (in *BucketInitParameters) DeepCopyInto(out *BucketInitParameters) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.SecretKeySecretRef != nil { + in, out := &in.SecretKeySecretRef, &out.SecretKeySecretRef + *out = new(v1.SecretKeySelector) + **out = **in + } if in.Versioning != nil { in, out := &in.Versioning, &out.Versioning *out = new(bool) @@ -1102,6 +1107,11 @@ func (in *ObjectInitParameters) DeepCopyInto(out *ObjectInitParameters) { (*out)[key] = outVal } } + if in.SecretKeySecretRef != nil { + in, out := &in.SecretKeySecretRef, &out.SecretKeySecretRef + *out = new(v1.SecretKeySelector) + **out = **in + } if in.Source != nil { in, out := &in.Source, &out.Source *out = new(string) diff --git a/apis/objectstorage/v1alpha1/zz_object_terraformed.go b/apis/objectstorage/v1alpha1/zz_object_terraformed.go index 16e3a9d..0f1e391 100755 --- a/apis/objectstorage/v1alpha1/zz_object_terraformed.go +++ b/apis/objectstorage/v1alpha1/zz_object_terraformed.go @@ -21,7 +21,7 @@ func (mg *Object) GetTerraformResourceType() string { // GetConnectionDetailsMapping for this Object func (tr *Object) GetConnectionDetailsMapping() map[string]string { - return map[string]string{"secret_key": "spec.forProvider.secretKeySecretRef"} + return map[string]string{"secret_key": "secretKeySecretRef"} } // GetObservation of this Object diff --git a/apis/objectstorage/v1alpha1/zz_object_types.go b/apis/objectstorage/v1alpha1/zz_object_types.go index 2fe1c13..521551b 100755 --- a/apis/objectstorage/v1alpha1/zz_object_types.go +++ b/apis/objectstorage/v1alpha1/zz_object_types.go @@ -91,6 +91,10 @@ type ObjectInitParameters struct { // +mapType=granular Metadata map[string]*string `json:"metadata,omitempty" tf:"metadata,omitempty"` + // The REQUIRED secret key to authenticate with. If it's not specified with the resource, you must provide its value by + // The REQUIRED S3 secret key with access to the target bucket. If not specified with the resource, you must provide its value by configuring the obj_secret_key, or, opting-in generating it implicitly at apply-time using obj_use_temp_keys at provider-level. + SecretKeySecretRef *v1.SecretKeySelector `json:"secretKeySecretRef,omitempty" tf:"-"` + // The path to a file that will be read and uploaded as raw bytes for the object content. The path must either be relative to the root module or absolute. // The source file to upload. Source *string `json:"source,omitempty" tf:"source,omitempty"` diff --git a/apis/vpc/v1alpha1/zz_generated.conversion_hubs.go b/apis/vpc/v1alpha1/zz_generated.conversion_hubs.go index 8975595..7a96feb 100755 --- a/apis/vpc/v1alpha1/zz_generated.conversion_hubs.go +++ b/apis/vpc/v1alpha1/zz_generated.conversion_hubs.go @@ -7,7 +7,7 @@ Copyright 2022 Upbound Inc. package v1alpha1 // Hub marks this type as a conversion hub. -func (tr *VPC) Hub() {} +func (tr *Subnet) Hub() {} // Hub marks this type as a conversion hub. -func (tr *Subnet) Hub() {} +func (tr *VPC) Hub() {} diff --git a/build b/build index 7233e36..231258d 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit 7233e36491dc8298d33f1feb1bf8c5056a960cac +Subproject commit 231258db281237379d8ec0c6e4af9d7c1ae5cc4a diff --git a/cmd/provider/main.go b/cmd/provider/main.go index 56a778a..ee7cc73 100644 --- a/cmd/provider/main.go +++ b/cmd/provider/main.go @@ -36,6 +36,7 @@ import ( "github.com/linode/provider-linode/internal/clients" "github.com/linode/provider-linode/internal/controller" "github.com/linode/provider-linode/internal/features" + linodemetrics "github.com/linode/provider-linode/internal/metrics" ) func main() { @@ -72,6 +73,7 @@ func main() { cfg, err := ctrl.GetConfig() kingpin.FatalIfError(err, "Cannot get API server rest config") + kingpin.FatalIfError(linodemetrics.SetupMetrics(), "Cannot setup Linode metrics hook") mgr, err := ctrl.NewManager(ratelimiter.LimitRESTConfig(cfg, *maxReconcileRate), ctrl.Options{ LeaderElection: *leaderElection, diff --git a/go.mod b/go.mod index b7022eb..a469c0e 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,15 @@ go 1.21 require ( dario.cat/mergo v1.0.0 - github.com/crossplane/crossplane-runtime v1.16.0-rc.1.0.20240424114634-8641eb2ba384 - github.com/crossplane/crossplane-tools v0.0.0-20230925130601-628280f8bf79 - github.com/crossplane/upjet v1.3.0 + github.com/crossplane/crossplane-runtime v1.16.0 + github.com/crossplane/crossplane-tools v0.0.0-20240516011917-bfb5045f0903 + github.com/crossplane/upjet v1.4.0 + github.com/go-resty/resty/v2 v2.12.0 github.com/hashicorp/terraform-json v0.21.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/linode/terraform-provider-linode/v2 v2.20.1 github.com/pkg/errors v0.9.1 + github.com/prometheus/client_golang v1.18.0 gopkg.in/alecthomas/kingpin.v2 v2.2.6 k8s.io/apimachinery v0.29.1 k8s.io/client-go v0.29.1 @@ -20,6 +22,7 @@ require ( require ( github.com/agext/levenshtein v1.2.3 // indirect + github.com/alecthomas/kingpin/v2 v2.4.0 // indirect github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/antchfx/htmlquery v1.2.4 // indirect @@ -47,7 +50,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/dave/jennifer v1.4.1 // indirect + github.com/dave/jennifer v1.7.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect @@ -60,7 +63,6 @@ require ( github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect - github.com/go-resty/resty/v2 v2.12.0 // indirect github.com/gobuffalo/flect v1.0.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -109,7 +111,6 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/muvaf/typewriter v0.0.0-20220131201631-921e94e8e8d7 // indirect github.com/oklog/run v1.0.0 // indirect - github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect @@ -121,6 +122,7 @@ require ( github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/xhit/go-str2duration/v2 v2.1.0 // indirect github.com/yuin/goldmark v1.4.13 // indirect github.com/zclconf/go-cty v1.14.3 // indirect github.com/zclconf/go-cty-yaml v1.0.3 // indirect diff --git a/go.sum b/go.sum index 8e92863..3f3dd64 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/ProtonMail/go-crypto v1.1.0-alpha.0/go.mod h1:rA3QumHc/FZ8pAHreoekgiA github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/kong v0.2.16/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -70,14 +72,14 @@ github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vc github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/crossplane/crossplane-runtime v1.16.0-rc.1.0.20240424114634-8641eb2ba384 h1:EswfDIEITA16CUWt78dVN0plbMBk8TdDfpbVXNeQJ1Y= -github.com/crossplane/crossplane-runtime v1.16.0-rc.1.0.20240424114634-8641eb2ba384/go.mod h1:Pz2tdGVMF6KDGzHZOkvKro0nKc8EzK0sb/nSA7pH4Dc= -github.com/crossplane/crossplane-tools v0.0.0-20230925130601-628280f8bf79 h1:HigXs5tEQxWz0fcj8hzbU2UAZgEM7wPe0XRFOsrtF8Y= -github.com/crossplane/crossplane-tools v0.0.0-20230925130601-628280f8bf79/go.mod h1:+e4OaFlOcmr0JvINHl/yvEYBrZawzTgj6pQumOH1SS0= -github.com/crossplane/upjet v1.3.0 h1:qRgcfqLz4M2v7enUku3xEriY5poc5XVbRl98nbvvu+E= -github.com/crossplane/upjet v1.3.0/go.mod h1:3pDVtCgyBc5f2Zx4K5HEPxxhjndmOc5CHCJNpIivK/g= -github.com/dave/jennifer v1.4.1 h1:XyqG6cn5RQsTj3qlWQTKlRGAyrTcsk1kUmWdZBzRjDw= -github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA= +github.com/crossplane/crossplane-runtime v1.16.0 h1:lz+l0wEB3qowdTmN7t0PZkfuNSvfOoEhQrEYFbYqMow= +github.com/crossplane/crossplane-runtime v1.16.0/go.mod h1:Pz2tdGVMF6KDGzHZOkvKro0nKc8EzK0sb/nSA7pH4Dc= +github.com/crossplane/crossplane-tools v0.0.0-20240516011917-bfb5045f0903 h1:bL8QbWkmzkdK7swURaaKEFiYS8+ib4fYU74eyRpCrYg= +github.com/crossplane/crossplane-tools v0.0.0-20240516011917-bfb5045f0903/go.mod h1:cN0Y7PFGQMM8mcagXVCbeQoKtipmFWQTPZYyziCPBUI= +github.com/crossplane/upjet v1.4.0 h1:twKCU8omU7VAA7E5fpbQkqDHjVnoTb8EXqmB805Q37o= +github.com/crossplane/upjet v1.4.0/go.mod h1:3pDVtCgyBc5f2Zx4K5HEPxxhjndmOc5CHCJNpIivK/g= +github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE= +github.com/dave/jennifer v1.7.0/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -328,6 +330,8 @@ github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21 github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= diff --git a/internal/clients/linode.go b/internal/clients/linode.go index f899c0e..358fd7d 100644 --- a/internal/clients/linode.go +++ b/internal/clients/linode.go @@ -9,6 +9,8 @@ import ( "encoding/json" "github.com/crossplane/crossplane-runtime/pkg/resource" + "github.com/go-resty/resty/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/types" @@ -18,6 +20,7 @@ import ( terraformsdk "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/linode/provider-linode/apis/v1beta1" + "github.com/linode/provider-linode/internal/metrics" "github.com/linode/terraform-provider-linode/v2/linode" "github.com/linode/terraform-provider-linode/v2/linode/helper" @@ -108,8 +111,15 @@ func configureNoForkLinodeclient(ctx context.Context, ps *terraform.Setup, p sch } ps.Meta = p.Meta() - + p.Meta().(*helper.ProviderMeta).Client.SetUserAgent("crossplane-provider-linode") + p.Meta().(*helper.ProviderMeta).Client.OnBeforeRequest(apiCallCounterMiddleware) fwProvider := linode.CreateFrameworkProviderWithMeta(version.ProviderVersion, p.Meta().(*helper.ProviderMeta)) + ps.FrameworkProvider = fwProvider return nil } + +func apiCallCounterMiddleware(r *resty.Request) error { + metrics.IncLinodeAPICall(r.URL, r.Method) + return nil +} diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go new file mode 100644 index 0000000..0d29e8c --- /dev/null +++ b/internal/metrics/metrics.go @@ -0,0 +1,24 @@ +package metrics + +import ( + "github.com/prometheus/client_golang/prometheus" + + k8smetrics "sigs.k8s.io/controller-runtime/pkg/metrics" +) + +var ( + metricsLinodeApiCalls = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "linode_api_calls_total", + Help: "Number of API calls to the Linode API", + }, []string{"url", "method"}) +) + +// SetupMetrics will register the known Prometheus metrics with controller-runtime's metrics registry +func SetupMetrics() error { + return k8smetrics.Registry.Register(metricsLinodeApiCalls) +} + +// IncLinodeAPICall will increment the linode_api_calls_total metric for the specified service, operation, and apiVersion tuple +func IncLinodeAPICall(url, method string) { + metricsLinodeApiCalls.WithLabelValues(url, method).Inc() +} diff --git a/package/crds/instance.linode.upbound.io_disks.yaml b/package/crds/instance.linode.upbound.io_disks.yaml index 109e5e1..b91fbfe 100644 --- a/package/crds/instance.linode.upbound.io_disks.yaml +++ b/package/crds/instance.linode.upbound.io_disks.yaml @@ -427,11 +427,34 @@ spec: type: string type: object type: object + rootPassSecretRef: + description: |- + The root user’s password on a newly-created Linode Disk when deploying from an Image. (Requires image) + This sets the root user's password on a newly-created Linode Disk when deploying from an Image. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object size: description: |- The size of the Disk in MB. NOTE: Resizing a disk will trigger a Linode reboot. The ID of the token. type: number + stackscriptDataSecretRef: + additionalProperties: + type: string + type: object stackscriptId: description: |- A StackScript ID that will cause the referenced StackScript to be run during deployment of this Disk. (Requires image) diff --git a/package/crds/instance.linode.upbound.io_instances.yaml b/package/crds/instance.linode.upbound.io_instances.yaml index b885665..23aa35c 100644 --- a/package/crds/instance.linode.upbound.io_instances.yaml +++ b/package/crds/instance.linode.upbound.io_instances.yaml @@ -1252,11 +1252,34 @@ spec: If true, this Disk is read-only. If true, this Disk is read-only. type: boolean + rootPassSecretRef: + description: |- + The initial password for the root user account. This value can not be imported. + The password that will be initialially assigned to the 'root' user account. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object size: description: |- The size of the Disk in MB. The size of the Disk in MB. type: number + stackscriptDataSecretRef: + additionalProperties: + type: string + type: object stackscriptId: description: |- The StackScript to deploy to the newly created Linode. If provided, 'image' must also be provided, and must be an Image that is compatible with this StackScript. This value can not be imported. Changing @@ -1373,6 +1396,25 @@ spec: If true, changes in Linode type will attempt to upsize or downsize implicitly created disks. This must be false if explicit disks are defined. This is an irreversible action as Linode disks cannot be automatically downsized. If true, changes in Linode type will attempt to upsize or downsize implicitly created disks. This must be false if explicit disks are defined. This is an irreversible action as Linode disks cannot be automatically downsized. type: boolean + rootPassSecretRef: + description: |- + The initial password for the root user account. This value can not be imported. + The password that will be initially assigned to the 'root' user account. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object sharedIpv4: description: |- A set of IPv4 addresses to be shared with the Instance. These IP addresses can be both private and public, but must be in the same region as the instance. @@ -1381,6 +1423,10 @@ spec: type: string type: array x-kubernetes-list-type: set + stackscriptDataSecretRef: + additionalProperties: + type: string + type: object stackscriptId: description: |- The StackScript to deploy to the newly created Linode. If provided, 'image' must also be provided, and must be an Image that is compatible with this StackScript. This value can not be imported. Changing diff --git a/package/crds/nodebalancer.linode.upbound.io_configs.yaml b/package/crds/nodebalancer.linode.upbound.io_configs.yaml index a340d5d..2ec244a 100644 --- a/package/crds/nodebalancer.linode.upbound.io_configs.yaml +++ b/package/crds/nodebalancer.linode.upbound.io_configs.yaml @@ -410,6 +410,44 @@ spec: The version of ProxyProtocol to use for the underlying NodeBalancer. This requires protocol to be tcp. (none, v1, v2) (Defaults to none) The version of ProxyProtocol to use for the underlying NodeBalancer. This requires protocol to be `tcp`. Valid values are `none`, `v1`, and `v2`. type: string + sslCertSecretRef: + description: |- + The certificate this port is serving. This is not returned. If set, this field will come back as . Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + The certificate this port is serving. This is not returned. If set, this field will come back as ``. Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object + sslKeySecretRef: + description: |- + The private key corresponding to this port's certificate. This is not returned. If set, this field will come back as . Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + The private key corresponding to this port's certificate. This is not returned. If set, this field will come back as ``. Please use the ssl_commonname and ssl_fingerprint to identify the certificate. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object stickiness: description: |- Controls how session stickiness is handled on this port. (none, table, http_cookie) diff --git a/package/crds/objectstorage.linode.upbound.io_buckets.yaml b/package/crds/objectstorage.linode.upbound.io_buckets.yaml index 54ff43c..ede8141 100644 --- a/package/crds/objectstorage.linode.upbound.io_buckets.yaml +++ b/package/crds/objectstorage.linode.upbound.io_buckets.yaml @@ -459,6 +459,25 @@ spec: type: string type: object type: array + secretKeySecretRef: + description: |- + The secret key to authenticate with. If not specified with the resource, its value can be + The S3 secret key to use for this resource. (Required for lifecycle_rule and versioning). If not specified with the resource, the value will be read from provider-level obj_secret_key, or, generated implicitly at apply-time if obj_use_temp_keys in provider configuration is set. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object versioning: description: |- Whether to enable versioning. Once you version-enable a bucket, it can never return to an unversioned state. You can, however, suspend versioning on that bucket. (Requires access_key and secret_key) diff --git a/package/crds/objectstorage.linode.upbound.io_objects.yaml b/package/crds/objectstorage.linode.upbound.io_objects.yaml index 2d66698..8d90516 100644 --- a/package/crds/objectstorage.linode.upbound.io_objects.yaml +++ b/package/crds/objectstorage.linode.upbound.io_objects.yaml @@ -430,6 +430,25 @@ spec: The metadata of this object type: object x-kubernetes-map-type: granular + secretKeySecretRef: + description: |- + The REQUIRED secret key to authenticate with. If it's not specified with the resource, you must provide its value by + The REQUIRED S3 secret key with access to the target bucket. If not specified with the resource, you must provide its value by configuring the obj_secret_key, or, opting-in generating it implicitly at apply-time using obj_use_temp_keys at provider-level. + properties: + key: + description: The key to select. + type: string + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - key + - name + - namespace + type: object source: description: |- The path to a file that will be read and uploaded as raw bytes for the object content. The path must either be relative to the root module or absolute.