func RunCreate(options *cli.CreateOptions) error {
	// Create our cluster resource
	name := options.Name
	var newCluster *cluster.Cluster
	if _, ok := cli.ProfileMapIndexed[options.Profile]; ok {
		newCluster = cli.ProfileMapIndexed[options.Profile].ProfileFunc(name)
	} else {
		return fmt.Errorf("Invalid profile [%s]", options.Profile)
	}

	if options.KubeConfigLocalFile != "" {
		if newCluster.Annotations == nil {
			newCluster.Annotations = make(map[string]string)
		}
		newCluster.Annotations[kubeconfig.ClusterAnnotationKubeconfigLocalFile] = options.KubeConfigLocalFile
	}

	if len(options.Set) > 0 {
		// Here we override Set options
		for _, set := range options.Set {
			parts := strings.SplitN(set, "=", 2)
			if len(parts) == 1 {
				continue
			}
			providerConfig := newCluster.ProviderConfig()
			err := cli.SwalkerWrite(strings.Title(parts[0]), providerConfig, parts[1])
			if err != nil {
				//fmt.Println(1)
				return fmt.Errorf("Invalid --set: %v", err)
			}
			newCluster.SetProviderConfig(providerConfig)
		}
	}

	if len(options.MasterSet) > 0 {
		// Here we override MasterSet options
		for _, set := range options.MasterSet {
			parts := strings.SplitN(set, "=", 2)
			if len(parts) == 1 {
				continue
			}

			for i, ms := range newCluster.MachineSets {
				isMaster := false
				for _, role := range ms.Spec.Template.Spec.Roles {
					if role == v1alpha1.MasterRole {
						isMaster = true
						break
					}
				}
				if !isMaster {
					continue
				}
				pcStr := ms.Spec.Template.Spec.ProviderConfig
				providerConfig := &cluster.MachineProviderConfig{}
				json.Unmarshal([]byte(pcStr), providerConfig)
				err := cli.SwalkerWrite(strings.Title(parts[0]), providerConfig, parts[1])
				if err != nil {
					//fmt.Println(2)
					return fmt.Errorf("Invalid --set: %v", err)
				}
				// Now set the provider config
				bytes, err := json.Marshal(providerConfig)
				if err != nil {
					logger.Critical("Unable to marshal provider config: %v", err)
					return err
				}
				str := string(bytes)
				newCluster.MachineSets[i].Spec.Template.Spec.ProviderConfig = str
			}

		}
	}

	if len(options.NodeSet) > 0 {
		// Here we override NodeSet options
		for _, set := range options.NodeSet {
			parts := strings.SplitN(set, "=", 2)
			if len(parts) == 1 {
				continue
			}
			for i, ms := range newCluster.MachineSets {
				isNode := false
				for _, role := range ms.Spec.Template.Spec.Roles {
					if role == v1alpha1.NodeRole {
						isNode = true
						break
					}
				}
				if !isNode {
					continue
				}
				pcStr := ms.Spec.Template.Spec.ProviderConfig
				providerConfig := &cluster.MachineProviderConfig{}
				json.Unmarshal([]byte(pcStr), providerConfig)
				err := cli.SwalkerWrite(strings.Title(parts[0]), providerConfig, parts[1])
				if err != nil {
					//fmt.Println(3)
					return fmt.Errorf("Invalid --set: %v", err)
				}
				// Now set the provider config
				bytes, err := json.Marshal(providerConfig)
				if err != nil {
					logger.Critical("Unable to marshal provider config: %v", err)
					return err
				}
				str := string(bytes)
				newCluster.MachineSets[i].Spec.Template.Spec.ProviderConfig = str
			}

		}
	}

	if len(options.AwsOptions.PolicyAttachments) > 0 {
		for i, ms := range newCluster.MachineSets {
			pcStr := ms.Spec.Template.Spec.ProviderConfig
			providerConfig := &cluster.MachineProviderConfig{}
			if err := json.Unmarshal([]byte(pcStr), providerConfig); err != nil {
				logger.Critical("Unable to unmarshal provider config: %v", err)
				return err
			}
			if providerConfig.ServerPool != nil && providerConfig.ServerPool.InstanceProfile != nil && providerConfig.ServerPool.InstanceProfile.Role != nil {
				providerConfig.ServerPool.InstanceProfile.Role.PolicyAttachments = options.AwsOptions.PolicyAttachments
			}
			// Now set the provider config
			bytes, err := json.Marshal(providerConfig)
			if err != nil {
				logger.Critical("Unable to marshal provider config: %v", err)
				return err
			}
			str := string(bytes)
			newCluster.MachineSets[i].Spec.Template.Spec.ProviderConfig = str
		}
	}

	if newCluster.ProviderConfig().Cloud == cluster.CloudGoogle && options.CloudID == "" {
		return fmt.Errorf("CloudID is required for google cloud. Please set it to your project ID")
	}

	providerConfig := newCluster.ProviderConfig()
	providerConfig.CloudId = options.CloudID
	newCluster.SetProviderConfig(providerConfig)

	// Expand state store path
	// Todo (@kris-nova) please pull this into a filepath package or something
	options.StateStorePath = cli.ExpandPath(options.StateStorePath)

	// Register state store and check if it exists
	stateStore, err := options.NewStateStore()
	if err != nil {
		return err
	} else if stateStore.Exists() {
		return fmt.Errorf("State store [%s] exists, will not overwrite. Delete existing profile [%s] and retry", name, options.StateStorePath+"/"+name)
	}

	// Init new state store with the cluster resource
	err = stateStore.Commit(newCluster)
	if err != nil {
		return fmt.Errorf("Unable to init state store: %v", err)
	}

	logger.Always("The state [%s/%s/cluster.yaml] has been created. You can edit the file, then run `kubicorn apply %s`", options.StateStorePath, name, name)
	return nil
}
func RunCreate(options *cli.CreateOptions) error {
	// Create our cluster resource
	name := options.Name
	var newCluster *cluster.Cluster
	if _, ok := cli.ProfileMapIndexed[options.Profile]; ok {
		newCluster = cli.ProfileMapIndexed[options.Profile].ProfileFunc(name)
	} else {
		return fmt.Errorf("Invalid profile [%s]", options.Profile)
	}

	if options.KubeConfigLocalFile != "" {
		if newCluster.Annotations == nil {
			newCluster.Annotations = make(map[string]string)
		}
		newCluster.Annotations[kubeconfig.ClusterAnnotationKubeconfigLocalFile] = options.KubeConfigLocalFile
	}

	if len(options.Set) > 0 {
		// Here we override Set options
		for _, set := range options.Set {
			parts := strings.SplitN(set, "=", 2)
			if len(parts) == 1 {
				continue
			}
			providerConfig := newCluster.ProviderConfig()
			err := cli.SwalkerWrite(strings.Title(parts[0]), providerConfig, parts[1])
			if err != nil {
				//fmt.Println(1)
				return fmt.Errorf("Invalid --set: %v", err)
			}
			newCluster.SetProviderConfig(providerConfig)
		}
	}

	if len(options.MasterSet) > 0 {
		// Here we override MasterSet options
		for _, set := range options.MasterSet {
			parts := strings.SplitN(set, "=", 2)
			if len(parts) == 1 {
				continue
			}

			for i, ms := range newCluster.MachineSets {
				isMaster := false
				for _, role := range ms.Spec.Template.Spec.Roles {
					if role == v1alpha1.MasterRole {
						isMaster = true
						break
					}
				}
				if !isMaster {
					continue
				}
				pcStr := ms.Spec.Template.Spec.ProviderConfig
				providerConfig := &cluster.MachineProviderConfig{}
				json.Unmarshal([]byte(pcStr), providerConfig)
				err := cli.SwalkerWrite(strings.Title(parts[0]), providerConfig, parts[1])
				if err != nil {
					//fmt.Println(2)
					return fmt.Errorf("Invalid --set: %v", err)
				}
				// Now set the provider config
				bytes, err := json.Marshal(providerConfig)
				if err != nil {
					logger.Critical("Unable to marshal provider config: %v", err)
					return err
				}
				str := string(bytes)
				newCluster.MachineSets[i].Spec.Template.Spec.ProviderConfig = str
			}

		}
	}

	if len(options.NodeSet) > 0 {
		// Here we override NodeSet options
		for _, set := range options.NodeSet {
			parts := strings.SplitN(set, "=", 2)
			if len(parts) == 1 {
				continue
			}
			for i, ms := range newCluster.MachineSets {
				isNode := false
				for _, role := range ms.Spec.Template.Spec.Roles {
					if role == v1alpha1.NodeRole {
						isNode = true
						break
					}
				}
				if !isNode {
					continue
				}
				pcStr := ms.Spec.Template.Spec.ProviderConfig
				providerConfig := &cluster.MachineProviderConfig{}
				json.Unmarshal([]byte(pcStr), providerConfig)
				err := cli.SwalkerWrite(strings.Title(parts[0]), providerConfig, parts[1])
				if err != nil {
					//fmt.Println(3)
					return fmt.Errorf("Invalid --set: %v", err)
				}
				// Now set the provider config
				bytes, err := json.Marshal(providerConfig)
				if err != nil {
					logger.Critical("Unable to marshal provider config: %v", err)
					return err
				}
				str := string(bytes)
				newCluster.MachineSets[i].Spec.Template.Spec.ProviderConfig = str
			}

		}
	}

	if len(options.AwsOptions.PolicyAttachments) > 0 {
		for i, ms := range newCluster.MachineSets {
			pcStr := ms.Spec.Template.Spec.ProviderConfig
			providerConfig := &cluster.MachineProviderConfig{}
			if err := json.Unmarshal([]byte(pcStr), providerConfig); err != nil {
				logger.Critical("Unable to unmarshal provider config: %v", err)
				return err
			}
			if providerConfig.ServerPool != nil && providerConfig.ServerPool.InstanceProfile != nil && providerConfig.ServerPool.InstanceProfile.Role != nil {
				providerConfig.ServerPool.InstanceProfile.Role.PolicyAttachments = options.AwsOptions.PolicyAttachments
			}
			// Now set the provider config
			bytes, err := json.Marshal(providerConfig)
			if err != nil {
				logger.Critical("Unable to marshal provider config: %v", err)
				return err
			}
			str := string(bytes)
			newCluster.MachineSets[i].Spec.Template.Spec.ProviderConfig = str
		}
	}

	if newCluster.ProviderConfig().Cloud == cluster.CloudGoogle && options.CloudID == "" {
		return fmt.Errorf("CloudID is required for google cloud. Please set it to your project ID")
	}

	providerConfig := newCluster.ProviderConfig()
	providerConfig.CloudId = options.CloudID
	newCluster.SetProviderConfig(providerConfig)

	// Expand state store path
	// Todo (@kris-nova) please pull this into a filepath package or something
	options.StateStorePath = cli.ExpandPath(options.StateStorePath)

	// Register state store and check if it exists
	stateStore, err := options.NewStateStore()
	if err != nil {
		return err
	} else if stateStore.Exists() {
		return fmt.Errorf("State store [%s] exists, will not overwrite. Delete existing profile [%s] and retry", name, options.StateStorePath+"/"+name)
	}

	// Init new state store with the cluster resource
	err = stateStore.Commit(newCluster)
	if err != nil {
		return fmt.Errorf("Unable to init state store: %v", err)
	}

	logger.Always("The state [%s/%s/cluster.yaml] has been created. You can edit the file, then run `kubicorn apply %s`", options.StateStorePath, name, name)
	return nil
}
// RunCreate is the starting point when a user runs the create command.