github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/provisioner/graphqlizer.go (about)

     1  package provisioner
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"reflect"
     7  	"text/template"
     8  
     9  	"github.com/sirupsen/logrus"
    10  
    11  	"fmt"
    12  
    13  	"strconv"
    14  
    15  	"github.com/Masterminds/sprig"
    16  	"github.com/kyma-project/control-plane/components/provisioner/pkg/gqlschema"
    17  )
    18  
    19  // Graphqlizer is responsible for converting Go objects to input arguments in graphql format
    20  type Graphqlizer struct{}
    21  
    22  func (g *Graphqlizer) ProvisionRuntimeInputToGraphQL(in gqlschema.ProvisionRuntimeInput) (string, error) {
    23  	return g.genericToGraphQL(in, `{
    24  		{{- if .RuntimeInput }}
    25  	  	runtimeInput: {{ RuntimeInputToGraphQL .RuntimeInput }},
    26  		{{- end }}
    27  		{{- if .ClusterConfig }}
    28  		clusterConfig: {{ ClusterConfigToGraphQL .ClusterConfig }},
    29  		{{- end }}
    30  		{{- if .KymaConfig }}
    31  		kymaConfig: {{ KymaConfigToGraphQL .KymaConfig }},
    32  		{{- end }}
    33  	}`)
    34  }
    35  
    36  func (g *Graphqlizer) RuntimeInputToGraphQL(in gqlschema.RuntimeInput) (string, error) {
    37  	return g.genericToGraphQL(in, `{
    38  		name: "{{.Name}}",
    39  		{{- if .Description }}
    40  		description: "{{.Description}}",
    41  		{{- end }}
    42  		{{- if .Labels }}
    43  		labels: {{ LabelsToGQL .Labels}},
    44  		{{- end }}
    45  	}`)
    46  }
    47  
    48  func (g *Graphqlizer) LabelsToGQL(in gqlschema.Labels) (string, error) {
    49  	return g.marshal(in), nil
    50  }
    51  
    52  func (g *Graphqlizer) ClusterConfigToGraphQL(in gqlschema.ClusterConfigInput) (string, error) {
    53  	return g.genericToGraphQL(in, `{
    54  		{{- if .GardenerConfig }}
    55  		gardenerConfig: {{ GardenerConfigInputToGraphQL .GardenerConfig }},
    56  		{{- end }}
    57  		{{- if .Administrators }}
    58  		administrators: {{.Administrators | marshal }},
    59  		{{- end }}
    60  	}`)
    61  }
    62  
    63  func (g *Graphqlizer) GardenerConfigInputToGraphQL(in gqlschema.GardenerConfigInput) (string, error) {
    64  	return g.genericToGraphQL(in, `{
    65  		{{- if .Name }}
    66  		name: "{{.Name}}",
    67  		{{- end }}
    68  		kubernetesVersion: "{{.KubernetesVersion}}",
    69  		{{- if .VolumeSizeGb }}
    70  		volumeSizeGB: {{.VolumeSizeGb }},
    71  		{{- end }}
    72  		machineType: "{{.MachineType}}",
    73  		{{- if .MachineImage }}
    74  		machineImage: "{{.MachineImage}}",
    75  		{{- end}}
    76  		{{- if .MachineImageVersion }}
    77  		machineImageVersion: "{{.MachineImageVersion}}",
    78  		{{- end }}
    79  		region: "{{.Region}}",
    80  		provider: "{{ .Provider }}",
    81  		{{- if .Purpose }}
    82  		purpose: "{{ .Purpose }}",
    83  		{{- end }}
    84  		{{- if .LicenceType }}
    85  		licenceType: "{{ .LicenceType }}",
    86  		{{- end }}
    87  		{{- if .DiskType }}
    88  		diskType: "{{.DiskType}}",
    89  		{{- end }}
    90  		targetSecret: "{{ .TargetSecret }}",
    91  		workerCidr: "{{ .WorkerCidr }}",
    92  		{{- if .PodsCidr }}
    93  		podsCidr: "{{ .PodsCidr }}",
    94  		{{- end }}
    95  		{{- if .ServicesCidr }}
    96  		servicesCidr: "{{ .ServicesCidr }}"
    97  		{{- end }}
    98  		autoScalerMin: {{ .AutoScalerMin }},
    99  		autoScalerMax: {{ .AutoScalerMax }},
   100  		maxSurge: {{ .MaxSurge }},
   101  		maxUnavailable: {{ .MaxUnavailable }},
   102  		{{- if .ExposureClassName }}
   103  		exposureClassName: "{{ .ExposureClassName }}",
   104  		{{- end }}
   105  		{{- if .EnableKubernetesVersionAutoUpdate }}
   106  		enableKubernetesVersionAutoUpdate: {{ .EnableKubernetesVersionAutoUpdate }},
   107  		{{- end }}
   108  		{{- if .EnableMachineImageVersionAutoUpdate }}
   109  		enableMachineImageVersionAutoUpdate: {{ .EnableMachineImageVersionAutoUpdate }},
   110  		{{- end }}
   111  		{{- if .ProviderSpecificConfig }}
   112  		providerSpecificConfig: {
   113  			{{- if .ProviderSpecificConfig.AzureConfig }}
   114  			azureConfig: {{ AzureProviderConfigInputToGraphQL .ProviderSpecificConfig.AzureConfig }},
   115  			{{- end}}
   116  			{{- if .ProviderSpecificConfig.GcpConfig }}
   117  			gcpConfig: {{ GCPProviderConfigInputToGraphQL .ProviderSpecificConfig.GcpConfig }},
   118  			{{- end}}
   119  			{{- if .ProviderSpecificConfig.AwsConfig }}
   120  			awsConfig: {{ AWSProviderConfigInputToGraphQL .ProviderSpecificConfig.AwsConfig }},
   121  			{{- end}}
   122  			{{- if .ProviderSpecificConfig.OpenStackConfig }}
   123  			openStackConfig: {{ OpenStackProviderConfigInputToGraphQL .ProviderSpecificConfig.OpenStackConfig }},
   124  			{{- end}}
   125  		}
   126  		{{- end}}
   127  		{{- if .OidcConfig }}
   128  		oidcConfig: {
   129  			clientID: "{{ .OidcConfig.ClientID }}",
   130  			issuerURL: "{{ .OidcConfig.IssuerURL }}",
   131  			groupsClaim: "{{ .OidcConfig.GroupsClaim }}",
   132  			signingAlgs: {{ .OidcConfig.SigningAlgs | marshal }},
   133  			usernameClaim: "{{ .OidcConfig.UsernameClaim }}",
   134  			usernamePrefix: "{{ .OidcConfig.UsernamePrefix }}",
   135  		}
   136  		{{- end }}
   137  		{{- if .DNSConfig }}
   138  		dnsConfig: {{ DNSConfigInputToGraphQL .DNSConfig }}
   139  		{{- end }}
   140  		{{- if .ControlPlaneFailureTolerance }}
   141  		controlPlaneFailureTolerance: "{{ .ControlPlaneFailureTolerance }}",
   142  		{{- end }}
   143  		{{- if .EuAccess }}
   144  		euAccess: {{ .EuAccess }},
   145  		{{- end }}
   146  		{{- if .ShootNetworkingFilterDisabled }}
   147  		shootNetworkingFilterDisabled: {{ .ShootNetworkingFilterDisabled }},
   148  		{{- end }}
   149  	}`)
   150  }
   151  
   152  func (g *Graphqlizer) DNSConfigInputToGraphQL(in gqlschema.DNSConfigInput) (string, error) {
   153  	return g.genericToGraphQL(in, `{
   154  			domain: "{{ .Domain }}",
   155  			{{- with .Providers }}
   156  			providers: [
   157  				{{- range . }}
   158  				{
   159  					domainsInclude: {{ .DomainsInclude | marshal }},
   160  					primary: {{ .Primary }},
   161  					secretName: "{{ .SecretName }}",
   162  					type: "{{ .Type }}",
   163  				}
   164  				{{- end }}
   165  			]
   166  			{{- end }}
   167  		}`)
   168  }
   169  
   170  func (g *Graphqlizer) AzureProviderConfigInputToGraphQL(in gqlschema.AzureProviderConfigInput) (string, error) {
   171  	return g.genericToGraphQL(in, `{
   172  		{{- if .EnableNatGateway}}
   173  		enableNatGateway: {{.EnableNatGateway}},
   174  		{{- end }}
   175  		vnetCidr: "{{.VnetCidr}}",
   176  		{{- if .Zones }}
   177  		zones: {{.Zones | marshal }},
   178  		{{- end }}
   179  		{{- with .AzureZones }}
   180  		azureZones: [
   181  			{{- range . }}
   182  			{
   183  				name: {{ .Name }},
   184  				cidr: "{{ .Cidr }}",
   185  			}
   186  			{{- end }}
   187  		]
   188  		{{- end }}
   189  	}`)
   190  }
   191  
   192  func (g *Graphqlizer) GCPProviderConfigInputToGraphQL(in gqlschema.GCPProviderConfigInput) (string, error) {
   193  	return fmt.Sprintf(`{ zones: %s }`, g.marshal(in.Zones)), nil
   194  }
   195  
   196  func (g *Graphqlizer) AWSProviderConfigInputToGraphQL(in gqlschema.AWSProviderConfigInput) (string, error) {
   197  	return g.genericToGraphQL(in, `{
   198  		vpcCidr: "{{.VpcCidr}}",
   199  		{{- with .AwsZones }}
   200  		awsZones: [
   201  			{{- range . }}
   202  			{
   203  				name: "{{ .Name }}",
   204  				workerCidr: "{{ .WorkerCidr }}",
   205  				publicCidr: "{{ .PublicCidr }}",
   206  				internalCidr: "{{ .InternalCidr }}",
   207  			}
   208  			{{- end }}
   209  		]
   210  		{{- end }}
   211  	}`)
   212  }
   213  
   214  func (g *Graphqlizer) OpenStackProviderConfigInputToGraphQL(in gqlschema.OpenStackProviderConfigInput) (string, error) {
   215  	return fmt.Sprintf(`{
   216  				zones: %s,
   217  				floatingPoolName: "%s",
   218  				cloudProfileName: "%s",
   219  				loadBalancerProvider: "%s"
   220  			}`, g.marshal(in.Zones), in.FloatingPoolName, in.CloudProfileName, in.LoadBalancerProvider), nil
   221  }
   222  
   223  func (g *Graphqlizer) KymaConfigToGraphQL(in gqlschema.KymaConfigInput) (string, error) {
   224  	return g.genericToGraphQL(in, `{
   225  		version: "{{ .Version }}",
   226  		{{- if .Profile }}
   227  		profile: {{ .Profile }},
   228  		{{- end }}
   229  		{{- if .ConflictStrategy }}
   230  		conflictStrategy: {{ .ConflictStrategy }},
   231  		{{- end }}
   232  		{{- with .Components }}
   233  		components: [
   234  			{{- range . }}
   235  			{
   236  				component: "{{ .Component }}",
   237  				namespace: "{{ .Namespace }}",
   238  				{{- if .SourceURL }}
   239  				sourceURL: "{{ .SourceURL }}",
   240  				{{- end }}
   241  				{{- if .ConflictStrategy }}
   242  				conflictStrategy: {{ .ConflictStrategy }},
   243  				{{- end }}
   244  				{{- with .Configuration }}
   245  				configuration: [
   246  					{{- range . }}
   247  					{
   248  						key: "{{ .Key }}",
   249  						value: {{ .Value | strQuote }},
   250  						{{- if .Secret }}
   251  						secret: true,
   252  						{{- end }}
   253  					}
   254  					{{- end }}
   255  				]
   256  				{{- end }}
   257  			}
   258  			{{- end }}
   259  		]
   260  	  	{{- end }}
   261  		{{- with .Configuration }}
   262  		configuration: [
   263  			{{- range . }}
   264  			{
   265  				key: "{{ .Key }}",
   266  				value: {{ .Value | strQuote }},
   267  				{{- if .Secret }}
   268  				secret: true,
   269  				{{- end }}
   270  			}
   271  			{{- end }}
   272  		]
   273  		{{- end }}
   274  	}`)
   275  }
   276  
   277  func (g *Graphqlizer) GardenerUpgradeInputToGraphQL(in gqlschema.GardenerUpgradeInput) (string, error) {
   278  	return g.genericToGraphQL(in, `{
   279  		{{- if .KubernetesVersion }}
   280  		kubernetesVersion: "{{.KubernetesVersion}}",
   281  		{{- end }}
   282  		{{- if .MachineType }}
   283  		machineType: "{{ .MachineType }}",
   284  		{{- end}}
   285  		{{- if .MachineImage }}
   286  		machineImage: "{{.MachineImage}}",
   287  		{{- end}}
   288  		{{- if .MachineImageVersion }}
   289  		machineImageVersion: "{{.MachineImageVersion}}",
   290  		{{- end }}
   291  		{{- if .AutoScalerMin }}
   292  		autoScalerMin: {{ .AutoScalerMin }},
   293  		{{- end }}
   294  		{{- if .AutoScalerMax }}
   295  		autoScalerMax: {{ .AutoScalerMax }},
   296  		{{- end }}
   297  		{{- if .MaxSurge }}
   298  		maxSurge: {{ .MaxSurge }},
   299  		{{- end }}
   300  		{{- if .MaxUnavailable }}
   301  		maxUnavailable: {{ .MaxUnavailable }},
   302  		{{- end }}
   303  		{{- if .ExposureClassName }}
   304  		exposureClassName: "{{ .ExposureClassName }}",
   305  		{{- end }}
   306  		{{- if .EnableKubernetesVersionAutoUpdate }}
   307  		enableKubernetesVersionAutoUpdate: {{ .EnableKubernetesVersionAutoUpdate }},
   308  		{{- end }}
   309  		{{- if .EnableMachineImageVersionAutoUpdate }}
   310  		enableMachineImageVersionAutoUpdate: {{ .EnableMachineImageVersionAutoUpdate }},
   311  		{{- end }}
   312  		{{- if .OidcConfig }}
   313  		oidcConfig: {
   314  			clientID: "{{ .OidcConfig.ClientID }}",
   315  			issuerURL: "{{ .OidcConfig.IssuerURL }}",
   316  			groupsClaim: "{{ .OidcConfig.GroupsClaim }}",
   317  			signingAlgs: {{ .OidcConfig.SigningAlgs | marshal }},
   318  			usernameClaim: "{{ .OidcConfig.UsernameClaim }}",
   319  			usernamePrefix: "{{ .OidcConfig.UsernamePrefix }}",
   320  		},
   321  		{{- end }}
   322          {{- if .ShootNetworkingFilterDisabled }}
   323          shootNetworkingFilterDisabled: {{ .ShootNetworkingFilterDisabled }},
   324  		{{- end }}
   325  	}`)
   326  }
   327  
   328  func (g *Graphqlizer) marshal(obj interface{}) string {
   329  	var out string
   330  
   331  	val := reflect.ValueOf(obj)
   332  
   333  	switch val.Kind() {
   334  	case reflect.Map:
   335  		s, err := g.genericToGraphQL(obj, `{ {{- range $k, $v := . }}{{ $k }}:{{ marshal $v }},{{ end -}} }`)
   336  		if err != nil {
   337  			logrus.Warnf("failed to marshal labels: %s", err.Error())
   338  			return ""
   339  		}
   340  		out = s
   341  	case reflect.Slice, reflect.Array:
   342  		s, err := g.genericToGraphQL(obj, `[{{ range $i, $e := . }}{{ if $i }},{{ end }}{{ marshal $e }}{{ end }}]`)
   343  		if err != nil {
   344  			logrus.Warnf("failed to marshal labels: %s", err.Error())
   345  			return ""
   346  		}
   347  		out = s
   348  	default:
   349  		marshalled, err := json.Marshal(obj)
   350  		if err != nil {
   351  			logrus.Warnf("failed to marshal labels: %s", err.Error())
   352  			return ""
   353  		}
   354  		out = string(marshalled)
   355  	}
   356  
   357  	return out
   358  }
   359  
   360  func (g *Graphqlizer) UpgradeRuntimeInputToGraphQL(in gqlschema.UpgradeRuntimeInput) (string, error) {
   361  	return g.genericToGraphQL(in, `{
   362  		kymaConfig: {{ KymaConfigToGraphQL .KymaConfig }}
   363  	}`)
   364  }
   365  
   366  func (g Graphqlizer) UpgradeShootInputToGraphQL(in gqlschema.UpgradeShootInput) (string, error) {
   367  	return g.genericToGraphQL(in, `{
   368  	gardenerConfig: {{ GardenerUpgradeInputToGraphQL .GardenerConfig }},
   369  	{{- if .Administrators }}
   370  	administrators: {{.Administrators | marshal }},
   371  	{{- end }}
   372  }`)
   373  }
   374  
   375  func (g *Graphqlizer) genericToGraphQL(obj interface{}, tmpl string) (string, error) {
   376  	fm := sprig.TxtFuncMap()
   377  	fm["marshal"] = g.marshal
   378  	fm["RuntimeInputToGraphQL"] = g.RuntimeInputToGraphQL
   379  	fm["ClusterConfigToGraphQL"] = g.ClusterConfigToGraphQL
   380  	fm["KymaConfigToGraphQL"] = g.KymaConfigToGraphQL
   381  	fm["GardenerConfigInputToGraphQL"] = g.GardenerConfigInputToGraphQL
   382  	fm["GardenerUpgradeInputToGraphQL"] = g.GardenerUpgradeInputToGraphQL
   383  	fm["AzureProviderConfigInputToGraphQL"] = g.AzureProviderConfigInputToGraphQL
   384  	fm["GCPProviderConfigInputToGraphQL"] = g.GCPProviderConfigInputToGraphQL
   385  	fm["AWSProviderConfigInputToGraphQL"] = g.AWSProviderConfigInputToGraphQL
   386  	fm["OpenStackProviderConfigInputToGraphQL"] = g.OpenStackProviderConfigInputToGraphQL
   387  	fm["DNSConfigInputToGraphQL"] = g.DNSConfigInputToGraphQL
   388  	fm["LabelsToGQL"] = g.LabelsToGQL
   389  	fm["strQuote"] = strconv.Quote
   390  
   391  	t, err := template.New("tmpl").Funcs(fm).Parse(tmpl)
   392  	if err != nil {
   393  		return "", fmt.Errorf("while parsing template: %w", err)
   394  	}
   395  
   396  	var b bytes.Buffer
   397  
   398  	if err := t.Execute(&b, obj); err != nil {
   399  		return "", fmt.Errorf("while executing template: %w", err)
   400  	}
   401  	return b.String(), nil
   402  }