Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin' into postgres_dedicated_ip_addr…
Browse files Browse the repository at this point in the history
…esses
  • Loading branch information
eberlep committed Dec 7, 2023
2 parents 3593a6f + 432e5d0 commit d4afa16
Show file tree
Hide file tree
Showing 10 changed files with 496 additions and 716 deletions.
80 changes: 71 additions & 9 deletions cmd/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net"
"net/http"
"os"
"slices"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -314,6 +315,8 @@ func newClusterCmd(c *config) *cobra.Command {
clusterCreateCmd.Flags().String("cni", "", "the network plugin used in this cluster, defaults to calico. please note that cilium support is still Alpha and we are happy to receive feedback. [optional]")
clusterCreateCmd.Flags().BoolP("enable-node-local-dns", "", false, "enables node local dns cache on the cluster nodes. [optional].")
clusterCreateCmd.Flags().BoolP("disable-forwarding-to-upstream-dns", "", false, "disables direct forwarding of queries to external dns servers when node-local-dns is enabled. All dns queries will go through coredns. [optional].")
clusterCreateCmd.Flags().StringSlice("kube-apiserver-acl-allowed-cidrs", []string{}, "comma-separated list of external CIDRs allowed to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")")
clusterCreateCmd.Flags().Bool("enable-kube-apiserver-acl", false, "restricts access from outside to the kube-apiserver to the source ip addresses set by --kube-apiserver-acl-allowed-cidrs [optional].")

must(clusterCreateCmd.MarkFlagRequired("name"))
must(clusterCreateCmd.MarkFlagRequired("project"))
Expand Down Expand Up @@ -387,20 +390,23 @@ func newClusterCmd(c *config) *cobra.Command {
clusterUpdateCmd.Flags().BoolP("disable-pod-security-policies", "", false, "disable pod security policies")
clusterUpdateCmd.Flags().String("audit", "on", "audit logging of cluster API access; can be off, on or splunk (logging to a predefined or custom splunk endpoint).")
clusterUpdateCmd.Flags().String("purpose", "", fmt.Sprintf("purpose of the cluster, can be one of %s. SLA is only given on production clusters.", strings.Join(completion.ClusterPurposes, "|")))
clusterUpdateCmd.Flags().StringSlice("egress", []string{}, "static egress ips per network, must be in the form <networkid>:<semicolon-separated ips>; e.g.: --egress internet:1.2.3.4;1.2.3.5 --egress extnet:123.1.1.1 [optional]. Use --egress none to remove all egress rules.")
clusterUpdateCmd.Flags().StringSlice("egress", []string{}, "static egress ips per network, must be in the form <networkid>:<semicolon-separated ips>; e.g.: --egress internet:1.2.3.4;1.2.3.5 --egress extnet:123.1.1.1 [optional]. Use \"--egress none\" to remove all egress rules.")
clusterUpdateCmd.Flags().StringSlice("external-networks", []string{}, "external networks of the cluster")
clusterUpdateCmd.Flags().Duration("healthtimeout", 0, "period (e.g. \"24h\") after which an unhealthy node is declared failed and will be replaced. (0 = provider-default)")
clusterUpdateCmd.Flags().Duration("draintimeout", 0, "period (e.g. \"3h\") after which a draining node will be forcefully deleted. (0 = provider-default)")
clusterUpdateCmd.Flags().String("maxsurge", "", "max number (e.g. 1) or percentage (e.g. 10%) of workers created during a update of the cluster.")
clusterUpdateCmd.Flags().String("maxunavailable", "", "max number (e.g. 0) or percentage (e.g. 10%) of workers that can be unavailable during a update of the cluster.")
clusterUpdateCmd.Flags().BoolP("autoupdate-kubernetes", "", false, "enables automatic updates of the kubernetes patch version of the cluster")
clusterUpdateCmd.Flags().BoolP("autoupdate-machineimages", "", false, "enables automatic updates of the worker node images of the cluster, be aware that this deletes worker nodes!")
clusterUpdateCmd.Flags().BoolP("reversed-vpn", "", false, "enables usage of reversed-vpn instead of konnectivity tunnel for worker connectivity.")
clusterUpdateCmd.Flags().Bool("encrypted-storage-classes", false, "enables the deployment of encrypted duros storage classes into the cluster. please refer to the user manual to properly use volume encryption.")
clusterUpdateCmd.Flags().String("default-storage-class", "", "set default storage class to given name, must be one of the managed storage classes")
clusterUpdateCmd.Flags().BoolP("disable-custom-default-storage-class", "", false, "if set to true, no default class is deployed, you have to set one of your storageclasses manually to default")
clusterUpdateCmd.Flags().BoolP("enable-node-local-dns", "", false, "enables node local dns cache on the cluster nodes. [optional]. WARNING: changing this value will lead to rolling of the worker nodes [optional]")
clusterUpdateCmd.Flags().BoolP("disable-forwarding-to-upstream-dns", "", false, "disables direct forwarding of queries to external dns servers when node-local-dns is enabled. All dns queries will go through coredns [optional].")
clusterUpdateCmd.Flags().StringSlice("kube-apiserver-acl-set-allowed-cidrs", []string{}, "comma-separated list of external CIDRs allowed to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")")
clusterUpdateCmd.Flags().StringSlice("kube-apiserver-acl-add-to-allowed-cidrs", []string{}, "comma-separated list of external CIDRs to add to the allowed CIDRs to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")")
clusterUpdateCmd.Flags().StringSlice("kube-apiserver-acl-remove-from-allowed-cidrs", []string{}, "comma-separated list of external CIDRs to be removed from the allowed CIDRs to connect to the kube-apiserver (e.g. \"212.34.68.0/24,212.34.89.0/27\")")
clusterUpdateCmd.Flags().Bool("enable-kube-apiserver-acl", false, "restricts access from outside to the kube-apiserver to the source ip addresses set by --kube-apiserver-acl-* [optional].")

must(clusterUpdateCmd.RegisterFlagCompletionFunc("version", c.comp.VersionListCompletion))
must(clusterUpdateCmd.RegisterFlagCompletionFunc("workerversion", c.comp.VersionListCompletion))
Expand Down Expand Up @@ -474,7 +480,7 @@ func newClusterCmd(c *config) *cobra.Command {
clusterMachineCmd.AddCommand(clusterMachineReinstallCmd)
clusterMachineCmd.AddCommand(clusterMachinePackagesCmd)

clusterReconcileCmd.Flags().String("operation", models.V1ClusterReconcileRequestOperationReconcile, "Executes a cluster \"reconcile\" operation.")
clusterReconcileCmd.Flags().String("operation", models.V1ClusterReconcileRequestOperationReconcile, fmt.Sprintf("Executes a cluster \"reconcile\" operation, can be one of %s.", strings.Join(completion.ClusterReconcileOperations, "|")))
must(clusterReconcileCmd.RegisterFlagCompletionFunc("operation", c.comp.ClusterReconcileOperationCompletion))

clusterIssuesCmd.Flags().String("id", "", "show clusters of given id")
Expand Down Expand Up @@ -666,8 +672,6 @@ func (c *config) clusterCreate() error {
AdditionalNetworks: networks,
PartitionID: &partition,
ClusterFeatures: &models.V1ClusterFeatures{
// always set reversed vpn for new clusters
ReversedVPN: pointer.Pointer("true"),
LogAcceptedConnections: &logAcceptedConnections,
DurosStorageEncryption: &encryptedStorageClasses,
},
Expand Down Expand Up @@ -719,6 +723,26 @@ func (c *config) clusterCreate() error {
scr.SystemComponents.NodeLocalDNS.DisableForwardToUpstreamDNS = &disableForwardToUpstreamDNS
}

if viper.IsSet("kube-apiserver-acl-allowed-cidrs") || viper.IsSet("enable-kube-apiserver-acl") {

if !viper.GetBool("yes-i-really-mean-it") && viper.IsSet("enable-kube-apiserver-acl") {
return fmt.Errorf("--enable-kube-apiserver-acl is set but you forgot to add --yes-i-really-mean-it")
}

if viper.GetBool("enable-kube-apiserver-acl") {
fmt.Println("WARNING: Restricting access to the kube-apiserver prevents FI-TS operators from helping you in case of any issues in your cluster.")
err = helper.Prompt("Are you sure? (y/n)", "y")
if err != nil {
return err
}
}

scr.KubeAPIServerACL = &models.V1KubeAPIServerACL{
CIDRs: viper.GetStringSlice("kube-apiserver-acl-allowed-cidrs"),
Disabled: pointer.Pointer(!viper.GetBool("enable-kube-apiserver-acl")),
}
}

egressRules := makeEgressRules(egress)
if len(egressRules) > 0 {
scr.EgressRules = egressRules
Expand Down Expand Up @@ -953,7 +977,6 @@ func (c *config) updateCluster(args []string) error {
defaultStorageClass := viper.GetString("default-storage-class")
disableDefaultStorageClass := viper.GetBool("disable-custom-default-storage-class")

reversedVPN := strconv.FormatBool(viper.GetBool("reversed-vpn"))
encryptedStorageClasses := strconv.FormatBool(viper.GetBool("encrypted-storage-classes"))

workerlabels, err := helper.LabelsToMap(workerlabelslice)
Expand Down Expand Up @@ -1009,9 +1032,6 @@ func (c *config) updateCluster(args []string) error {
if viper.IsSet("encrypted-storage-classes") {
clusterFeatures.DurosStorageEncryption = &encryptedStorageClasses
}
if viper.IsSet("reversed-vpn") {
clusterFeatures.ReversedVPN = &reversedVPN
}
if viper.IsSet("logacceptedconns") {
clusterFeatures.LogAcceptedConnections = &logAcceptedConnections
}
Expand Down Expand Up @@ -1210,6 +1230,48 @@ func (c *config) updateCluster(args []string) error {
cur.AdditionalNetworks = firewallNetworks
}

if viper.IsSet("kube-apiserver-acl-set-allowed-cidrs") || viper.IsSet("enable-kube-apiserver-acl") ||
viper.IsSet("kube-apiserver-acl-add-to-allowed-cidrs") || viper.IsSet("kube-apiserver-acl-remove-from-allowed-cidrs") {

newACL := current.KubeAPIServerACL
if newACL == nil {
newACL = &models.V1KubeAPIServerACL{
CIDRs: []string{},
Disabled: pointer.Pointer(true),
}
}

if viper.IsSet("enable-kube-apiserver-acl") {
if !viper.GetBool("yes-i-really-mean-it") {
return fmt.Errorf("--enable-kube-apiserver-acl is set but you forgot to add --yes-i-really-mean-it")
}
newACL.Disabled = pointer.Pointer(!viper.GetBool("enable-kube-apiserver-acl"))
}

if viper.IsSet("enable-kube-apiserver-acl") && viper.GetBool("enable-kube-apiserver-acl") {
fmt.Println("WARNING: Restricting access to the kube-apiserver prevents FI-TS operators from helping you in case of any issues in your cluster.")
err = helper.Prompt("Are you sure? (y/n)", "y")
if err != nil {
return err
}
}

for _, r := range viper.GetStringSlice("kube-apiserver-acl-remove-from-allowed-cidrs") {
newACL.CIDRs = slices.DeleteFunc(newACL.CIDRs, func(s string) bool {
return s == r
})
}
newACL.CIDRs = append(newACL.CIDRs, viper.GetStringSlice("kube-apiserver-acl-add-to-allowed-cidrs")...)

if viper.IsSet("kube-apiserver-acl-set-allowed-cidrs") {
newACL.CIDRs = viper.GetStringSlice("kube-apiserver-acl-set-allowed-cidrs")
}

slices.Sort(newACL.CIDRs)
newACL.CIDRs = slices.Compact(newACL.CIDRs)
cur.KubeAPIServerACL = newACL
}

if purpose != "" {
if *cur.Maintenance.AutoUpdate.KubernetesVersion && *current.Purpose == string(v1beta1.ShootPurposeEvaluation) && purpose != string(v1beta1.ShootPurposeEvaluation) {
fmt.Print("\nHint: Kubernetes auto updates will still be enabled after this update.\n\n")
Expand Down
8 changes: 7 additions & 1 deletion cmd/completion/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ import (
)

var (
ClusterPurposes = []string{"production", "development", "evaluation", "infrastructure"}
ClusterPurposes = []string{"production", "development", "evaluation", "infrastructure"}
ClusterReconcileOperations = []string{
models.V1ClusterReconcileRequestOperationReconcile,
models.V1ClusterReconcileRequestOperationRetry,
models.V1ClusterReconcileRequestOperationMaintain,
models.V1ClusterReconcileRequestOperationRotateDashSSHDashKeypair,
}
PodSecurityDefaults = []string{
models.V1KubernetesDefaultPodSecurityStandardRestricted,
models.V1KubernetesDefaultPodSecurityStandardBaseline,
Expand Down
7 changes: 7 additions & 0 deletions cmd/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"strings"
"time"

"github.com/go-openapi/runtime"
"github.com/go-openapi/strfmt"
"gopkg.in/yaml.v3"
k8syaml "sigs.k8s.io/yaml"
)
Expand Down Expand Up @@ -177,3 +179,8 @@ func MustPrintKubernetesResource(in any) {
}
fmt.Printf("---\n%s", string(y))
}

func ClientNoAuth() runtime.ClientAuthInfoWriterFunc {
noAuth := func(_ runtime.ClientRequest, _ strfmt.Registry) error { return nil }
return runtime.ClientAuthInfoWriterFunc(noAuth)
}
48 changes: 45 additions & 3 deletions cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import (
"os"
"strings"

"github.com/Masterminds/semver/v3"
"github.com/fi-ts/cloudctl/cmd/helper"
"github.com/fi-ts/cloudctl/pkg/api"
"github.com/metal-stack/metal-lib/auth"
"github.com/metal-stack/v"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
Expand All @@ -18,9 +21,11 @@ func newLoginCmd(c *config) *cobra.Command {
Short: "login user and receive token",
Long: "login and receive token that will be used to authenticate commands.",
RunE: func(cmd *cobra.Command, args []string) error {
var (
console io.Writer
handler auth.TokenHandlerFunc
)

var console io.Writer
var handler auth.TokenHandlerFunc
if viper.GetBool("print-only") {
// do not store, only print to console
handler = printTokenHandler
Expand Down Expand Up @@ -60,7 +65,44 @@ func newLoginCmd(c *config) *cobra.Command {
config.SuccessMessage = fmt.Sprintf(`Please close this page and return to your terminal. Manage your session on: <a href=%q>%s</a>`, ctx.IssuerURL+"/account", ctx.IssuerURL+"/account")
}

return auth.OIDCFlow(config)
err := auth.OIDCFlow(config)
if err != nil {
return err
}

resp, err := c.cloud.Version.Info(nil, helper.ClientNoAuth())
if err != nil {
return err
}
if resp.Payload != nil && resp.Payload.MinClientVersion != nil {
minVersion := *resp.Payload.MinClientVersion
parsedMinVersion, err := semver.NewVersion(minVersion)
if err != nil {
return fmt.Errorf("required cloudctl minimum version:%q is not semver parsable:%w", minVersion, err)
}

// This is a developer build
if !strings.HasPrefix(v.Version, "v") {
return nil
}

thisVersion, err := semver.NewVersion(v.Version)
if err != nil {
return fmt.Errorf("cloudctl version:%q is not semver parsable:%w", v.Version, err)
}

if thisVersion.LessThan(parsedMinVersion) {
return fmt.Errorf("your cloudctl version:%s is smaller than the required minimum version:%s, please run `cloudctl update do` to update to the supported version", thisVersion, minVersion)
}

if !thisVersion.Equal(parsedMinVersion) {
fmt.Println()
fmt.Printf("WARNING: Your cloudctl version %q might not compatible with the cloud-api (supported version is %q). Please run `cloudctl update do` to update to the supported version.", thisVersion, minVersion)
fmt.Println()
}
}

return nil
},
PreRun: bindPFlags,
}
Expand Down
3 changes: 3 additions & 0 deletions cmd/output/shootprinter.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ func (s ShootIssuesTablePrinter) Print(data []*models.V1ClusterResponse) {

func shootData(shoot *models.V1ClusterResponse, withIssues bool) ([]string, []string, []string) {
shootStats := newShootStats(shoot.Status)
if (*shoot).KubeAPIServerACL != nil && !*shoot.KubeAPIServerACL.Disabled {
shootStats.apiServer += "🔒"
}

maintainEmoji := ""
var issues []string
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func newRootCmd() *cobra.Command {
rootCmd.AddCommand(newAuditCmd(cfg))
rootCmd.AddCommand(newClusterCmd(cfg))
rootCmd.AddCommand(newDashboardCmd(cfg))
rootCmd.AddCommand(newUpdateCmd(name))
rootCmd.AddCommand(newUpdateCmd(cfg, name))
rootCmd.AddCommand(newLoginCmd(cfg))
rootCmd.AddCommand(newLogoutCmd(cfg))
rootCmd.AddCommand(newWhoamiCmd())
Expand Down
44 changes: 40 additions & 4 deletions cmd/update.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package cmd

import (
"github.com/metal-stack/updater"
"github.com/fi-ts/cloudctl/cmd/helper"
"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/metal-stack/metal-lib/pkg/pointer"
"github.com/metal-stack/updater"
)

func newUpdateCmd(name string) *cobra.Command {
func newUpdateCmd(c *config, name string) *cobra.Command {
updateCmd := &cobra.Command{
Use: "update",
Short: "update the program",
Expand All @@ -14,7 +18,11 @@ func newUpdateCmd(name string) *cobra.Command {
Use: "check",
Short: "check for update of the program",
RunE: func(cmd *cobra.Command, args []string) error {
u, err := updater.New("fi-ts", name, name)
desired, err := getMinimumClientVersion(c)
if err != nil {
return err
}
u, err := updater.New("fi-ts", name, name, desired)
if err != nil {
return err
}
Expand All @@ -25,16 +33,44 @@ func newUpdateCmd(name string) *cobra.Command {
Use: "do",
Short: "do the update of the program",
RunE: func(cmd *cobra.Command, args []string) error {
u, err := updater.New("fi-ts", name, name)
var desired *string

if !viper.IsSet("version") {
var err error
desired, err = getMinimumClientVersion(c)
if err != nil {
return err
}
}

if viper.IsSet("version") && viper.GetString("version") != "latest" {
desired = pointer.Pointer(viper.GetString("version"))
}

u, err := updater.New("fi-ts", name, name, desired)
if err != nil {
return err
}

return u.Do()
},
}

updateCmd.Flags().StringP("version", "v", "", `the version to update to, by default updates to the supported version, use "latest" to update to latest version`)

updateCmd.AddCommand(updateCheckCmd)
updateCmd.AddCommand(updateDoCmd)

return updateCmd
}

func getMinimumClientVersion(c *config) (*string, error) {
resp, err := c.cloud.Version.Info(nil, helper.ClientNoAuth())
if err != nil {
return nil, err
}
if resp.Payload != nil && resp.Payload.MinClientVersion != nil {
return resp.Payload.MinClientVersion, nil
}
return nil, nil
}
1 change: 1 addition & 0 deletions cmd/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ func Test_newVersionCmd(t *testing.T) {
server:
builddate: null
gitsha1: null
minclientversion: null
name: cloudctl
revision: null
version: null
Expand Down
Loading

0 comments on commit d4afa16

Please sign in to comment.