Apply commit label on resources created/updated when '--commitlabel' flag is passed (#2279)
This commit is contained in:
@@ -128,7 +128,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
|
|
||||||
if toSpec {
|
if toSpec {
|
||||||
|
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
@@ -169,7 +169,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
|
|
||||||
if toSpec {
|
if toSpec {
|
||||||
|
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (opts *CreateSubCommand) run(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir = util.GetSpecDir(input)
|
specDir = util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ func CreatePackage(input cli.Input, client client.Interface, pkgName string, pkg
|
|||||||
|
|
||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
// if a package with the same spec exists, don't create a new spec file
|
// if a package with the same spec exists, don't create a new spec file
|
||||||
fr, err := spec.ReadSpecs(util.GetSpecDir(input), util.GetSpecIgnore(input))
|
fr, err := spec.ReadSpecs(util.GetSpecDir(input), util.GetSpecIgnore(input), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error reading specs")
|
return nil, errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ func CreateArchive(client client.Interface, input cli.Input, includeFiles []stri
|
|||||||
} else if input.Bool(flagkey.SpecSave) {
|
} else if input.Bool(flagkey.SpecSave) {
|
||||||
// check if this AUS exists in the specs; if so, don't create a new one
|
// check if this AUS exists in the specs; if so, don't create a new one
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error reading specs")
|
return nil, errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func (opts *ApplySubCommand) do(input cli.Input) error {
|
|||||||
func (opts *ApplySubCommand) run(input cli.Input) error {
|
func (opts *ApplySubCommand) run(input cli.Input) error {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
|
applyCommitLabel := input.Bool(flagkey.SpecApplyCommitLabel)
|
||||||
deleteResources := input.Bool(flagkey.SpecDelete)
|
deleteResources := input.Bool(flagkey.SpecDelete)
|
||||||
watchResources := input.Bool(flagkey.SpecWatch)
|
watchResources := input.Bool(flagkey.SpecWatch)
|
||||||
waitForBuild := input.Bool(flagkey.SpecWait)
|
waitForBuild := input.Bool(flagkey.SpecWait)
|
||||||
@@ -112,7 +112,7 @@ func (opts *ApplySubCommand) run(input cli.Input) error {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
// read all specs
|
// read all specs
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, applyCommitLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
@@ -626,7 +626,7 @@ func applyPackages(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
keep = true
|
keep = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if keep && existingObj.Status.BuildStatus == fv1.BuildStatusSucceeded {
|
if keep && isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && existingObj.Status.BuildStatus == fv1.BuildStatusSucceeded {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -726,7 +726,7 @@ func applyFunctions(fclient client.Interface, fr *FissionResources, delete bool)
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -809,7 +809,7 @@ func applyEnvironments(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -892,7 +892,7 @@ func applyHTTPTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -975,7 +975,7 @@ func applyKubernetesWatchTriggers(fclient client.Interface, fr *FissionResources
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -1058,7 +1058,7 @@ func applyTimeTriggers(fclient client.Interface, fr *FissionResources, delete bo
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -1141,7 +1141,7 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d
|
|||||||
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
existingObj, ok := existent[mapKey(&o.ObjectMeta)]
|
||||||
if ok {
|
if ok {
|
||||||
// ok, a resource with the same name exists, is it the same?
|
// ok, a resource with the same name exists, is it the same?
|
||||||
if reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
if isObjectMetaEqual(existingObj.ObjectMeta, o.ObjectMeta) && reflect.DeepEqual(existingObj.Spec, o.Spec) {
|
||||||
// nothing to do on the server
|
// nothing to do on the server
|
||||||
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
metadataMap[mapKey(&o.ObjectMeta)] = existingObj.ObjectMeta
|
||||||
} else {
|
} else {
|
||||||
@@ -1184,3 +1184,27 @@ func applyMessageQueueTriggers(fclient client.Interface, fr *FissionResources, d
|
|||||||
|
|
||||||
return metadataMap, &ras, nil
|
return metadataMap, &ras, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isObjectMetaEqual(existingObj, newObj metav1.ObjectMeta) bool {
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(existingObj.Labels, newObj.Labels) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
existingAnnotations := make(map[string]string)
|
||||||
|
newAnnotations := make(map[string]string)
|
||||||
|
|
||||||
|
for existingObjKey, existingObjVal := range existingObj.Annotations {
|
||||||
|
if existingObjKey != FISSION_DEPLOYMENT_NAME_KEY && existingObjKey != FISSION_DEPLOYMENT_UID_KEY {
|
||||||
|
existingAnnotations[existingObjKey] = existingObjVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for newObjKey, newObjVal := range newObj.Annotations {
|
||||||
|
if newObjKey != FISSION_DEPLOYMENT_NAME_KEY && newObjKey != FISSION_DEPLOYMENT_UID_KEY {
|
||||||
|
newAnnotations[newObjKey] = newObjVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.DeepEqual(existingAnnotations, newAnnotations)
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func Commands() *cobra.Command {
|
|||||||
RunE: wrapper.Wrapper(Apply),
|
RunE: wrapper.Wrapper(Apply),
|
||||||
}
|
}
|
||||||
wrapper.SetFlags(applyCmd, flag.FlagSet{
|
wrapper.SetFlags(applyCmd, flag.FlagSet{
|
||||||
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecDelete, flag.SpecWait, flag.SpecWatch, flag.SpecValidation},
|
Optional: []flag.Flag{flag.SpecDir, flag.SpecIgnore, flag.SpecDelete, flag.SpecWait, flag.SpecWatch, flag.SpecValidation, flag.SpecApplyCommitLabel},
|
||||||
})
|
})
|
||||||
|
|
||||||
destroyCmd := &cobra.Command{
|
destroyCmd := &cobra.Command{
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func (opts *DestroySubCommand) run(input cli.Input) error {
|
|||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
|
|
||||||
// read everything
|
// read everything
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ func (opts *ListSubCommand) run(input cli.Input) error {
|
|||||||
// get specdir, specignore and read the deployID
|
// get specdir, specignore and read the deployID
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ func SpecSave(resource interface{}, specFile string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fr, err := ReadSpecs(specDir, util.SPEC_IGNORE_FILE)
|
fr, err := ReadSpecs(specDir, util.SPEC_IGNORE_FILE, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
@@ -526,9 +526,19 @@ func (fr *FissionResources) trackSourceMap(kind string, newobj *metav1.ObjectMet
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply commit label to the object metadata
|
||||||
|
func applyCommitLabel(commitLabelVal string, m *metav1.ObjectMeta) {
|
||||||
|
if len(commitLabelVal) != 0 {
|
||||||
|
if m.Labels == nil {
|
||||||
|
m.Labels = make(map[string]string)
|
||||||
|
}
|
||||||
|
m.Labels[util.COMMIT_LABEL] = commitLabelVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ParseYaml takes one yaml document, figures out its type, parses it, and puts it in
|
// ParseYaml takes one yaml document, figures out its type, parses it, and puts it in
|
||||||
// the right list in the given fission resources set.
|
// the right list in the given fission resources set.
|
||||||
func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
func (fr *FissionResources) ParseYaml(b []byte, loc *Location, commitLabelVal string) error {
|
||||||
var m *metav1.ObjectMeta
|
var m *metav1.ObjectMeta
|
||||||
|
|
||||||
// Figure out the object type by unmarshaling into the TypeMeta struct; then
|
// Figure out the object type by unmarshaling into the TypeMeta struct; then
|
||||||
@@ -547,6 +557,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.Packages = append(fr.Packages, v)
|
fr.Packages = append(fr.Packages, v)
|
||||||
case "Function":
|
case "Function":
|
||||||
var v fv1.Function
|
var v fv1.Function
|
||||||
@@ -555,6 +566,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.Functions = append(fr.Functions, v)
|
fr.Functions = append(fr.Functions, v)
|
||||||
case "Environment":
|
case "Environment":
|
||||||
var v fv1.Environment
|
var v fv1.Environment
|
||||||
@@ -563,6 +575,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.Environments = append(fr.Environments, v)
|
fr.Environments = append(fr.Environments, v)
|
||||||
case "HTTPTrigger":
|
case "HTTPTrigger":
|
||||||
var v fv1.HTTPTrigger
|
var v fv1.HTTPTrigger
|
||||||
@@ -570,8 +583,8 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.HttpTriggers = append(fr.HttpTriggers, v)
|
fr.HttpTriggers = append(fr.HttpTriggers, v)
|
||||||
case "KubernetesWatchTrigger":
|
case "KubernetesWatchTrigger":
|
||||||
var v fv1.KubernetesWatchTrigger
|
var v fv1.KubernetesWatchTrigger
|
||||||
@@ -580,6 +593,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.KubernetesWatchTriggers = append(fr.KubernetesWatchTriggers, v)
|
fr.KubernetesWatchTriggers = append(fr.KubernetesWatchTriggers, v)
|
||||||
case "TimeTrigger":
|
case "TimeTrigger":
|
||||||
var v fv1.TimeTrigger
|
var v fv1.TimeTrigger
|
||||||
@@ -588,6 +602,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.TimeTriggers = append(fr.TimeTriggers, v)
|
fr.TimeTriggers = append(fr.TimeTriggers, v)
|
||||||
case "MessageQueueTrigger":
|
case "MessageQueueTrigger":
|
||||||
var v fv1.MessageQueueTrigger
|
var v fv1.MessageQueueTrigger
|
||||||
@@ -596,6 +611,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
m = &v.ObjectMeta
|
m = &v.ObjectMeta
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.MessageQueueTriggers = append(fr.MessageQueueTriggers, v)
|
fr.MessageQueueTriggers = append(fr.MessageQueueTriggers, v)
|
||||||
|
|
||||||
// The following are not CRDs
|
// The following are not CRDs
|
||||||
@@ -606,6 +622,7 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
fr.DeploymentConfig = v
|
fr.DeploymentConfig = v
|
||||||
case "ArchiveUploadSpec":
|
case "ArchiveUploadSpec":
|
||||||
var v types.ArchiveUploadSpec
|
var v types.ArchiveUploadSpec
|
||||||
@@ -613,10 +630,12 @@ func (fr *FissionResources) ParseYaml(b []byte, loc *Location) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
return errors.Wrap(err, fmt.Sprintf("Failed to parse %v in %v", tm.Kind, loc))
|
||||||
}
|
}
|
||||||
|
|
||||||
m = &metav1.ObjectMeta{
|
m = &metav1.ObjectMeta{
|
||||||
Name: v.Name,
|
Name: v.Name,
|
||||||
Namespace: "",
|
Namespace: "",
|
||||||
}
|
}
|
||||||
|
applyCommitLabel(commitLabelVal, m)
|
||||||
fr.ArchiveUploadSpecs = append(fr.ArchiveUploadSpecs, v)
|
fr.ArchiveUploadSpecs = append(fr.ArchiveUploadSpecs, v)
|
||||||
default:
|
default:
|
||||||
// no need to error out just because there's some extra files around;
|
// no need to error out just because there's some extra files around;
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import (
|
|||||||
"github.com/fission/fission/pkg/fission-cli/console"
|
"github.com/fission/fission/pkg/fission-cli/console"
|
||||||
"github.com/fission/fission/pkg/fission-cli/util"
|
"github.com/fission/fission/pkg/fission-cli/util"
|
||||||
"github.com/fission/fission/pkg/utils"
|
"github.com/fission/fission/pkg/utils"
|
||||||
|
"github.com/fission/fission/pkg/utils/gitrepo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValidateSubCommand struct {
|
type ValidateSubCommand struct {
|
||||||
@@ -54,7 +55,7 @@ func (opts *ValidateSubCommand) run(input cli.Input) error {
|
|||||||
// this will error on parse errors and on duplicates
|
// this will error on parse errors and on duplicates
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := ReadSpecs(specDir, specIgnore)
|
fr, err := ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error reading specs")
|
return errors.Wrap(err, "error reading specs")
|
||||||
}
|
}
|
||||||
@@ -198,7 +199,7 @@ func isResourceConflicts(deployUID string, specObj fv1.MetadataAccessor, cluster
|
|||||||
|
|
||||||
// ReadSpecs reads all specs in the specified directory and returns a parsed set of
|
// ReadSpecs reads all specs in the specified directory and returns a parsed set of
|
||||||
// fission resources.
|
// fission resources.
|
||||||
func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
func ReadSpecs(specDir, specIgnore string, applyCommitLabel bool) (*FissionResources, error) {
|
||||||
|
|
||||||
// make sure spec directory exists before continue
|
// make sure spec directory exists before continue
|
||||||
if _, err := os.Stat(specDir); os.IsNotExist(err) {
|
if _, err := os.Stat(specDir); os.IsNotExist(err) {
|
||||||
@@ -225,6 +226,21 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get absolute path of specdir
|
||||||
|
if !filepath.IsAbs(specDir) {
|
||||||
|
cwd, err := filepath.Abs("./")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
specDir = filepath.Join(cwd, specDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
var gr *gitrepo.GitRepo
|
||||||
|
// check if applyCommitLabel flag is true
|
||||||
|
if applyCommitLabel {
|
||||||
|
gr = gitrepo.NewGitRepo(specDir)
|
||||||
|
}
|
||||||
|
|
||||||
var result *multierror.Error
|
var result *multierror.Error
|
||||||
|
|
||||||
// Users can organize the specdir into subdirs if they want to.
|
// Users can organize the specdir into subdirs if they want to.
|
||||||
@@ -239,16 +255,24 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if file matches any path in .specignore file
|
||||||
if ignoreParser.MatchesPath(path) {
|
if ignoreParser.MatchesPath(path) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fileCommitLabelVal string
|
||||||
|
// check if applyCommitLabel is true and specdir is tracked by git repo
|
||||||
|
if applyCommitLabel {
|
||||||
|
fileCommitLabelVal, _ = gr.GetFileCommitLabel(path)
|
||||||
|
}
|
||||||
|
|
||||||
// read
|
// read
|
||||||
b, err := os.ReadFile(path)
|
b, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle the case where there are multiple YAML docs per file. go-yaml
|
// handle the case where there are multiple YAML docs per file. go-yaml
|
||||||
// doesn't support this directly, yet.
|
// doesn't support this directly, yet.
|
||||||
docs := bytes.Split(b, []byte("\n---"))
|
docs := bytes.Split(b, []byte("\n---"))
|
||||||
@@ -260,7 +284,7 @@ func ReadSpecs(specDir, specIgnore string) (*FissionResources, error) {
|
|||||||
err = fr.ParseYaml(d, &Location{
|
err = fr.ParseYaml(d, &Location{
|
||||||
Path: path,
|
Path: path,
|
||||||
Line: lines,
|
Line: lines,
|
||||||
})
|
}, fileCommitLabelVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// collect all errors so user can fix them all
|
// collect all errors so user can fix them all
|
||||||
result = multierror.Append(result, err)
|
result = multierror.Append(result, err)
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ func (opts *CreateSubCommand) complete(input cli.Input) error {
|
|||||||
if input.Bool(flagkey.SpecSave) {
|
if input.Bool(flagkey.SpecSave) {
|
||||||
specDir := util.GetSpecDir(input)
|
specDir := util.GetSpecDir(input)
|
||||||
specIgnore := util.GetSpecIgnore(input)
|
specIgnore := util.GetSpecIgnore(input)
|
||||||
fr, err := spec.ReadSpecs(specDir, specIgnore)
|
fr, err := spec.ReadSpecs(specDir, specIgnore, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
return errors.Wrap(err, fmt.Sprintf("error reading spec in '%v'", specDir))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,16 +193,17 @@ var (
|
|||||||
PkgSrcChecksum = Flag{Type: String, Name: flagkey.PkgSrcChecksum, Usage: "SHA256 checksum of source archive when providing URL"}
|
PkgSrcChecksum = Flag{Type: String, Name: flagkey.PkgSrcChecksum, Usage: "SHA256 checksum of source archive when providing URL"}
|
||||||
PkgInsecure = Flag{Type: Bool, Name: flagkey.PkgInsecure, Usage: "Skip generating SHA256 checksum for file integrity validation"}
|
PkgInsecure = Flag{Type: Bool, Name: flagkey.PkgInsecure, Usage: "Skip generating SHA256 checksum for file integrity validation"}
|
||||||
|
|
||||||
SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"}
|
SpecSave = Flag{Type: Bool, Name: flagkey.SpecSave, Usage: "Save to the spec directory instead of creating on cluster"}
|
||||||
SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"}
|
SpecDir = Flag{Type: String, Name: flagkey.SpecDir, Usage: "Directory to store specs, defaults to ./specs"}
|
||||||
SpecName = Flag{Type: String, Name: flagkey.SpecName, Usage: "Name for the app, applied to resources as a Kubernetes annotation"}
|
SpecName = Flag{Type: String, Name: flagkey.SpecName, Usage: "Name for the app, applied to resources as a Kubernetes annotation"}
|
||||||
SpecDeployID = Flag{Type: String, Name: flagkey.SpecDeployID, Aliases: []string{"id"}, Usage: "Deployment ID for the spec deployment config"}
|
SpecDeployID = Flag{Type: String, Name: flagkey.SpecDeployID, Aliases: []string{"id"}, Usage: "Deployment ID for the spec deployment config"}
|
||||||
SpecWait = Flag{Type: Bool, Name: flagkey.SpecWait, Usage: "Wait for package builds"}
|
SpecWait = Flag{Type: Bool, Name: flagkey.SpecWait, Usage: "Wait for package builds"}
|
||||||
SpecWatch = Flag{Type: Bool, Name: flagkey.SpecWatch, Usage: "Watch local files for change, and re-apply specs as necessary"}
|
SpecWatch = Flag{Type: Bool, Name: flagkey.SpecWatch, Usage: "Watch local files for change, and re-apply specs as necessary"}
|
||||||
SpecDelete = Flag{Type: Bool, Name: flagkey.SpecDelete, Usage: "Allow apply to delete resources that no longer exist in the specification"}
|
SpecDelete = Flag{Type: Bool, Name: flagkey.SpecDelete, Usage: "Allow apply to delete resources that no longer exist in the specification"}
|
||||||
SpecDry = Flag{Type: Bool, Name: flagkey.SpecDry, Usage: "View the generated specs"}
|
SpecDry = Flag{Type: Bool, Name: flagkey.SpecDry, Usage: "View the generated specs"}
|
||||||
SpecValidation = Flag{Type: String, Name: flagkey.SpecValidate, Usage: "Turns server side validations of Fission objects on/off"}
|
SpecValidation = Flag{Type: String, Name: flagkey.SpecValidate, Usage: "Turns server side validations of Fission objects on/off"}
|
||||||
SpecIgnore = Flag{Type: String, Name: flagkey.SpecIgnore, Usage: fmt.Sprintf("File containing specs to be ignored inside --specdir, defaults to %v", util.SPEC_IGNORE_FILE)}
|
SpecIgnore = Flag{Type: String, Name: flagkey.SpecIgnore, Usage: fmt.Sprintf("File containing specs to be ingored inside --specdir, defaults to %v", util.SPEC_IGNORE_FILE)}
|
||||||
|
SpecApplyCommitLabel = Flag{Type: Bool, Name: flagkey.SpecApplyCommitLabel, Usage: "Apply commit label to the resources"}
|
||||||
|
|
||||||
SupportOutput = Flag{Type: String, Name: flagkey.SupportOutput, Short: "o", Usage: "Output directory to save dump archive/files", DefaultValue: flagkey.DefaultSpecOutputDir}
|
SupportOutput = Flag{Type: String, Name: flagkey.SupportOutput, Short: "o", Usage: "Output directory to save dump archive/files", DefaultValue: flagkey.DefaultSpecOutputDir}
|
||||||
SupportNoZip = Flag{Type: Bool, Name: flagkey.SupportNoZip, Usage: "Save dump information into multiple files instead of single zip file"}
|
SupportNoZip = Flag{Type: Bool, Name: flagkey.SupportNoZip, Usage: "Save dump information into multiple files instead of single zip file"}
|
||||||
|
|||||||
@@ -144,16 +144,17 @@ const (
|
|||||||
PkgStatus = "status"
|
PkgStatus = "status"
|
||||||
PkgOrphan = "orphan"
|
PkgOrphan = "orphan"
|
||||||
|
|
||||||
SpecSave = "spec"
|
SpecSave = "spec"
|
||||||
SpecDir = "specdir"
|
SpecDir = "specdir"
|
||||||
SpecName = resourceName
|
SpecName = resourceName
|
||||||
SpecDeployID = "deployid"
|
SpecDeployID = "deployid"
|
||||||
SpecWait = "wait"
|
SpecWait = "wait"
|
||||||
SpecWatch = "watch"
|
SpecWatch = "watch"
|
||||||
SpecDelete = "delete"
|
SpecDelete = "delete"
|
||||||
SpecDry = "dry"
|
SpecDry = "dry"
|
||||||
SpecValidate = "validation"
|
SpecValidate = "validation"
|
||||||
SpecIgnore = "specignore"
|
SpecIgnore = "specignore"
|
||||||
|
SpecApplyCommitLabel = "commitlabel"
|
||||||
|
|
||||||
SupportOutput = Output
|
SupportOutput = Output
|
||||||
SupportNoZip = "nozip"
|
SupportNoZip = "nozip"
|
||||||
|
|||||||
@@ -19,4 +19,5 @@ package util
|
|||||||
// fission-cli options
|
// fission-cli options
|
||||||
const (
|
const (
|
||||||
SPEC_IGNORE_FILE = ".specignore"
|
SPEC_IGNORE_FILE = ".specignore"
|
||||||
|
COMMIT_LABEL = "commit"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Fission Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package gitrepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GitRepo struct {
|
||||||
|
setupDone bool
|
||||||
|
isGitRepo bool
|
||||||
|
repo *git.Repository
|
||||||
|
status git.Status
|
||||||
|
dirPath string
|
||||||
|
gitRepoRootPath string // absolute path of the root of the git repository
|
||||||
|
commitID string // commit ID the HEAD of the repository is poitning to
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGitRepo creates new GitRepo struct
|
||||||
|
// checks if the given directory path is part of git repository
|
||||||
|
// accordingly updates the fields of GitRepo struct and returns it
|
||||||
|
func NewGitRepo(dirPath string) *GitRepo {
|
||||||
|
|
||||||
|
var g *GitRepo = &GitRepo{}
|
||||||
|
var err error
|
||||||
|
|
||||||
|
g.dirPath = dirPath
|
||||||
|
g.setupDone = true
|
||||||
|
|
||||||
|
// check if directory is tracked by git repo
|
||||||
|
g.repo, err = git.PlainOpenWithOptions(dirPath, &git.PlainOpenOptions{DetectDotGit: true})
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
workTree, err := g.repo.Worktree()
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
g.status, err = workTree.Status()
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.status == nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
plumbRef, err := g.repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract short commit ID
|
||||||
|
g.commitID = plumbRef.Hash().String()[:7]
|
||||||
|
|
||||||
|
// get the root path of git repository
|
||||||
|
g.gitRepoRootPath = workTree.Filesystem.Root()
|
||||||
|
|
||||||
|
g.isGitRepo = true
|
||||||
|
return g
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsGitRepo returns if the initialized directory path is tracked by git repo
|
||||||
|
func (g *GitRepo) IsGitRepo() bool {
|
||||||
|
return g.setupDone && g.isGitRepo
|
||||||
|
}
|
||||||
|
|
||||||
|
// getFileCommitLabel returns the value of 'commit' label
|
||||||
|
// for the resources present in the file
|
||||||
|
/*
|
||||||
|
The value of the `commit` label for different status of the file is as follows:
|
||||||
|
| Git File Status | Label Value |
|
||||||
|
|---------------------------------------|----------------------|
|
||||||
|
| New untracked file | untracked |
|
||||||
|
| New staged file | staged |
|
||||||
|
| Tracked file with changes in worktree | <commitID>-unstaged |
|
||||||
|
| Tracked file with changes staged | <commitID>-staged |
|
||||||
|
| Tracked file with clean commit | <commitID> |
|
||||||
|
*/
|
||||||
|
func (g *GitRepo) GetFileCommitLabel(filePath string) (string, error) {
|
||||||
|
|
||||||
|
if !g.setupDone {
|
||||||
|
return "", errors.New(`GitRepo is not setup. It has to be created by calling 'NewGitRepo' function,
|
||||||
|
then this function has to be called.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !g.isGitRepo {
|
||||||
|
return "", errors.Errorf(`directory: %s doesn't belong to git repository.`, g.dirPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// filepath in the git repository
|
||||||
|
splitPathList := strings.Split(filePath, g.gitRepoRootPath+string(os.PathSeparator))
|
||||||
|
if len(splitPathList) != 2 {
|
||||||
|
return "", errors.Errorf("error finding the git repository path of %s", filePath)
|
||||||
|
}
|
||||||
|
gitFilePath := splitPathList[1]
|
||||||
|
gitFileStatus := g.status.File(gitFilePath)
|
||||||
|
|
||||||
|
// check if file is tracked
|
||||||
|
if !g.status.IsUntracked(gitFilePath) {
|
||||||
|
|
||||||
|
// unstaged file
|
||||||
|
if gitFileStatus.Worktree == git.Modified {
|
||||||
|
return fmt.Sprintf("%s-unstaged", g.commitID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// newly staged file
|
||||||
|
if gitFileStatus.Staging == git.Added {
|
||||||
|
return "staged", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// staged file
|
||||||
|
if gitFileStatus.Staging == git.Modified {
|
||||||
|
return fmt.Sprintf("%s-staged", g.commitID), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if file is committed already
|
||||||
|
oc, err := g.repo.Log(&git.LogOptions{FileName: &gitFilePath})
|
||||||
|
if err != nil {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = oc.Next()
|
||||||
|
defer oc.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// File not tracked by git and/or not committed
|
||||||
|
return "untracked", nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// File tracked by git and has been committed
|
||||||
|
return g.commitID, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user