export

package
v0.1.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 10, 2023 License: Apache-2.0 Imports: 20 Imported by: 1

Documentation

Index

Constants

View Source
const (
	NamespacesKey           = "namespaces"
	NamespacesShorthand     = "n"
	DistinctByLabelKey      = "distinct-by-label"
	OutputLocationKey       = "output"
	OutputLocationShorthand = "o"
	OutputTypeKey           = "output-type"
	OutputTypeDefault       = OutputTypeSingleFile
	OutputTypeSingleFile    = "single-file"
	OutputTypeDirectory     = "dir"
	OutputFormatKey         = "format"
	OutputFormatDefault     = OutputFormatYAML
	OutputFormatYAML        = "yaml"
	OutputFormatJSON        = "json"
)

Variables

View Source
var ExportCmd = &cobra.Command{
	Use:   "export",
	Short: "Export Otterize intents from network mapper",
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		return mapperclient.WithClient(func(c *mapperclient.Client) error {
			err := validateOutputFlags()
			if err != nil {
				return err
			}

			ctxTimeout, cancel := context.WithTimeout(context.Background(), 10*time.Second)
			defer cancel()
			namespacesFilter := viper.GetStringSlice(NamespacesKey)
			var intentsFromMapperWithLabels []mapperclient.ServiceIntentsWithLabelsServiceIntents
			if viper.IsSet(DistinctByLabelKey) {
				includeLabels := []string{viper.GetString(DistinctByLabelKey)}
				intentsFromMapperV1018, err := c.ServiceIntentsWithLabels(ctxTimeout, namespacesFilter, includeLabels)
				if err != nil {
					if httpErr := (mapperclient.HTTPError{}); errors.As(err, &httpErr) && httpErr.StatusCode == http.StatusUnprocessableEntity {
						prints.PrintCliStderr("You've specified --%s, but your network mapper does not support this capability. Please upgrade.", DistinctByLabelKey)
					}
					return err
				}
				intentsFromMapperWithLabels = intentsFromMapperV1018
			} else {
				intentsFromMapperV1017, err := c.ServiceIntents(ctxTimeout, namespacesFilter)
				if err != nil {
					return err
				}
				intentsFromMapperWithLabels = lo.Map(intentsFromMapperV1017,
					func(item mapperclient.ServiceIntentsUpToMapperV017ServiceIntents, _ int) mapperclient.ServiceIntentsWithLabelsServiceIntents {
						return mapperclient.ServiceIntentsWithLabelsServiceIntents{
							Client: mapperclient.ServiceIntentsWithLabelsServiceIntentsClientOtterizeServiceIdentity{
								NamespacedNameFragment: item.Client.NamespacedNameFragment,
							},
							Intents: lo.Map(item.Intents, func(item mapperclient.ServiceIntentsUpToMapperV017ServiceIntentsIntentsOtterizeServiceIdentity, _ int) mapperclient.ServiceIntentsWithLabelsServiceIntentsIntentsOtterizeServiceIdentity {
								return mapperclient.ServiceIntentsWithLabelsServiceIntentsIntentsOtterizeServiceIdentity{
									NamespacedNameFragment: item.NamespacedNameFragment,
								}
							}),
						}
					})
			}

			groupedIntents := make(map[distinctKey]v1alpha2.ClientIntents, 0)

			for _, serviceIntents := range intentsFromMapperWithLabels {
				intentList := make([]v1alpha2.Intent, 0)
				serviceDistinctKey := distinctKey{
					Name:      serviceIntents.Client.Name,
					Namespace: serviceIntents.Client.Namespace,
				}

				if viper.IsSet(DistinctByLabelKey) {
					serviceDistinctKey.Namespace = ""
					if len(serviceIntents.Client.Labels) == 1 && serviceIntents.Client.Labels[0].Key == viper.GetString(DistinctByLabelKey) {
						serviceDistinctKey.LabelValue = serviceIntents.Client.Labels[0].Value
					} else {
						serviceDistinctKey.LabelValue = "no_value"
					}
				}

				for _, serviceIntent := range serviceIntents.Intents {
					intent := v1alpha2.Intent{
						Name: serviceIntent.Name,
					}

					if len(serviceIntent.Namespace) != 0 && serviceIntent.Namespace != serviceIntents.Client.Namespace {
						intent.Name = fmt.Sprintf("%s.%s", serviceIntent.Name, serviceIntent.Namespace)
					}
					intentList = append(intentList, intent)
				}

				intentsOutput := v1alpha2.ClientIntents{
					TypeMeta: v1.TypeMeta{
						Kind:       consts.IntentsKind,
						APIVersion: consts.IntentsAPIVersion,
					},
					ObjectMeta: v1.ObjectMeta{
						Name:      serviceIntents.Client.Name,
						Namespace: serviceIntents.Client.Namespace,
					},
					Spec: &v1alpha2.IntentsSpec{Service: v1alpha2.Service{Name: serviceIntents.Client.Name}},
				}

				if len(intentList) != 0 {
					intentsOutput.Spec.Calls = intentList
				}

				if currentIntents, ok := groupedIntents[serviceDistinctKey]; ok {
					if isCallsDifferent(currentIntents.Spec.Calls, intentsOutput.Spec.Calls) {
						prints.PrintCliStderr("Warning: intents for service `%s` in namespace `%s` differ from intents for service `%s` in namespace `%s`. Discarding intents from namespace %s. Unsafe to apply intents.",
							currentIntents.Name, currentIntents.Namespace, intentsOutput.Name, intentsOutput.Namespace, intentsOutput.Namespace)
						continue
					}
				}
				groupedIntents[serviceDistinctKey] = intentsOutput
			}

			if viper.GetString(OutputLocationKey) != "" {
				switch outputTypeVal := viper.GetString(OutputTypeKey); {
				case outputTypeVal == OutputTypeSingleFile:
					err := writeIntentsFile(viper.GetString(OutputLocationKey), lo.Values(groupedIntents))
					if err != nil {
						return err
					}
					output.PrintStderr("Successfully wrote intents into %s", viper.GetString(OutputLocationKey))
				case outputTypeVal == OutputTypeDirectory:
					err := os.MkdirAll(viper.GetString(OutputLocationKey), 0700)
					if err != nil {
						return fmt.Errorf("could not create dir %s: %w", viper.GetString(OutputLocationKey), err)
					}

					for groupKey, intent := range groupedIntents {
						filePath := fmt.Sprintf("%s.yaml", groupKey.String())
						if err != nil {
							return err
						}

						filePath = filepath.Join(viper.GetString(OutputLocationKey), filePath)
						err := writeIntentsFile(filePath, []v1alpha2.ClientIntents{intent})
						if err != nil {
							return err
						}
					}
					output.PrintStderr("Successfully wrote intents into %s", viper.GetString(OutputLocationKey))
				default:
					return fmt.Errorf("unexpected output type %s, use one of (%s, %s)", outputTypeVal, OutputTypeSingleFile, OutputTypeDirectory)
				}

			} else {
				formatted, err := getFormattedIntents(lo.Values(groupedIntents))
				if err != nil {
					return err
				}
				output.PrintStdout(formatted)
			}
			return nil
		})
	},
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL