Skip to content

Commit

Permalink
added timestamp to version, and redid bisect a different approach. Ho…
Browse files Browse the repository at this point in the history
…wever, it does not work as intended because when specifying username and password attribute/value pairs, they aren't connected so it just searched for each field/value pair independently, returns version 1 instead of version 5.
  • Loading branch information
djarotech committed Aug 17, 2018
1 parent 8d97aed commit 686773f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 137 deletions.
Binary file modified docs/versions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 20 additions & 18 deletions pkg/apiserver/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,29 +231,31 @@ func getHistory(request *restful.Request, response *restful.Response) {
func bisect(request *restful.Request, response *restful.Response) {
fmt.Println("Inside bisect")
resourceName := request.PathParameter("resource-id")
requestPath := request.Request.URL.Path
resourcePathSlice := strings.Split(requestPath, "/")
resourceKind := resourcePathSlice[6] // Kind is 7th element in the slice

var provenanceInfo string
provenanceInfo = "Resource Name:" + resourceName + " Resource Kind:" + resourceKind
//TODO: find out how to get entire query string, split on &, and pass in an array of fields/values to the bisect method.
field1 := request.QueryParameter("field1")
value1 := request.QueryParameter("value1")

field2 := request.QueryParameter("field2")
value2 := request.QueryParameter("value2")
provenanceInfo = provenanceInfo + " Field1:" + field1 + " Value1: " + value1
provenanceInfo = provenanceInfo + " Field2:" + field2 + " Value2: " + value2 + "\n"

fmt.Printf("ProvenanceInfo:%v", provenanceInfo)

requestPath := request.Request.URL.String()
// resourcePathSlice := strings.Split(requestPath, "/")
// resourceKind := resourcePathSlice[6] // Kind is 7th element in the slice
fmt.Println(requestPath)
strs := strings.Split(requestPath, "/")
// assuming that the last slash is where the query starts.
// so the URL parameters are rearranged alphabetically
// apis/kubeprovenance.cloudark.io/v1/namespaces/default/postgreses/client25/bisect?field1=username&field2=password&value1=pallavi&value2=pass123
// field1=username&field2=password&value1=pallavi&value2=pass123
args := strings.Split(strs[len(strs)-1], "?")[1] //get rid of bisect?
argMap := make(map[string]string)
argsArray := strings.Split(args, "&")
for _, val := range argsArray {
fieldToValue := strings.Split(val, "=")
argMap[fieldToValue[0]] = fieldToValue[1]
}
// var provenanceInfo string
// provenanceInfo = "Resource Name:" + resourceName + " Resource Kind:" + resourceKind
// fmt.Println(provenanceInfo)
intendedProvObj := provenance.FindProvenanceObjectByName(resourceName, provenance.AllProvenanceObjects)
if intendedProvObj == nil {
s := fmt.Sprintf("Could not find any provenance history for resource name: %s", resourceName)
response.Write([]byte(s))
} else {
response.Write([]byte("Version: " + intendedProvObj.ObjectFullHistory.Bisect(field1, value1, field2, value2)))
response.Write([]byte(intendedProvObj.ObjectFullHistory.Bisect(argMap)))
response.Write([]byte(string("\n")))
}
}
Expand Down
210 changes: 91 additions & 119 deletions pkg/provenance/provenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type ObjectLineage map[int]Spec
type Spec struct {
AttributeToData map[string]interface{}
Version int
Timestamp string
}

type ProvenanceOfObject struct {
Expand Down Expand Up @@ -147,11 +148,16 @@ func (o ObjectLineage) GetVersions() string {
}
sort.Ints(s)
//get all versions, sort by version, make string array of them
versions := make([]string, 0)
specs := make([]Spec, 0)
for _, version := range s {
versions = append(versions, fmt.Sprint(version)) //cast int to string
specs = append(specs, o[version])
}
//get all versions, sort by version, make string array of them
outputs := make([]string, 0)
for _, spec := range specs {
outputs = append(outputs, fmt.Sprintf("%s: Version %d", spec.Timestamp, spec.Version)) //cast int to string
}
return "[" + strings.Join(versions, ", ") + "]\n"
return "[" + strings.Join(outputs, ", \n") + "]\n"
}

//what happens if I delete the object?
Expand Down Expand Up @@ -195,7 +201,7 @@ func (o ObjectLineage) SpecHistoryInterval(vNumStart, vNumEnd int) string {
return strings.Join(specStrings, "\n")
}

func (o ObjectLineage) Bisect(field1, value1, field2, value2 string) string {
func (o ObjectLineage) Bisect(argMap map[string]string) string {
s := make([]int, 0)
for _, value := range o {
s = append(s, value.Version)
Expand All @@ -206,110 +212,99 @@ func (o ObjectLineage) Bisect(field1, value1, field2, value2 string) string {
for _, version := range s {
specs = append(specs, o[version]) //cast Spec to String
}
// fmt.Println(specs)
noSpecFound := fmt.Sprintf("Bisect for field %s: %s, %s: %s was not successful. Custom resource never reached this state.", field1, value1, field2, value2)

if len(specs) == 1 {
//check

u, ok1 := specs[0].AttributeToData[field1]
if !ok1 {
fmt.Printf("Field %s not found.\n", field1)
return noSpecFound
}
p, ok2 := specs[0].AttributeToData[field2]
if !ok2 {
fmt.Printf("Field %s not found.\n", field2)
return noSpecFound
}
users, ok1 := p.([]string)
if !ok1 {
fmt.Printf("Type assertion failed. Underlying data is incorrect and is not a slice of strings: %s\n", u)
return noSpecFound
}
passwords, ok2 := u.([]string)
if !ok2 {
fmt.Printf("Type assertion failed. Underlying data is incorrect and is not a slice of strings: %s\n", p)
return noSpecFound
allAttributeValuePairs := make([][]string, 0)
for key, value := range argMap {
attributeValueSlice := make([]string, 2)
if strings.Contains(key, "field") {
//find associated value in argMap
fieldNum, err := strconv.Atoi(key[5:])
if err != nil {
return fmt.Sprintf("Failure, could not convert %s. Invalid Query parameters.", key)
}
//find assocaited value1
valueOfKey, ok := argMap["value"+strconv.Itoa(fieldNum)]
if !ok {
return fmt.Sprintf("Could not find an associated value for field: %s", key)
}
attributeValueSlice[0] = value
attributeValueSlice[1] = valueOfKey
allAttributeValuePairs = append(allAttributeValuePairs, attributeValueSlice)
}
}
// fmt.Printf("attributeValuePairs%s\n", allAttributeValuePairs)
andGate := make([]bool, len(allAttributeValuePairs))
for _, spec := range specs {
index := 0
satisfied := false
for _, pair := range allAttributeValuePairs {
qkey := pair[0]
qval := pair[1]
//each qkey qval has to be satisfied
for mkey, mvalue := range spec.AttributeToData {
vString, ok1 := mvalue.(string)
if ok1 {
fmt.Println("a")
if qkey == mkey && qval == vString {
satisfied = true
break
}
}
vStringSlice, ok2 := mvalue.([]string)
if ok2 {
fmt.Println("b")
for _, str := range vStringSlice {
if qkey == mkey && qval == str {
satisfied = true
break
}
}
}
vSliceMap, ok3 := mvalue.([]map[string]string)
if ok3 {
fmt.Println("c")
for _, mymap := range vSliceMap {
for okey, ovalue := range mymap {
if qkey == okey && qval == ovalue {
satisfied = true
break
}
}
}
}

for i, v := range users {
if value1 == v && passwords[i] == value2 {
return "Version: " + strconv.Itoa(1)
}
andGate[index] = satisfied
index += 1
}
} else { //there is more than one spec. More than one Event found in the log
for _, spec := range specs {
//check
u, ok1 := spec.AttributeToData[field1]
if !ok1 {
fmt.Printf("Field %s not found.\n", field1)
return noSpecFound
}
p, ok2 := spec.AttributeToData[field2]
if !ok2 {
fmt.Printf("Field %s not found.\n", field2)
return noSpecFound
}
users, ok1 := u.([]string)
if !ok1 {
fmt.Printf("Type assertion failed. Underlying data is incorrect and is not a slice of strings: %s\n", u)
return noSpecFound
}
passwords, ok2 := p.([]string)
if !ok2 {
fmt.Printf("Type assertion failed. Underlying data is incorrect and is not a slice of strings: %s\n", p)
return noSpecFound
}

for i1, v1 := range users {
if value1 == v1 && passwords[i1] == value2 {
return "Version: " + strconv.Itoa(spec.Version)
}
allTrue := true
for _, b := range andGate {
if !b {
allTrue = false
}
}
fmt.Println(andGate)
if allTrue {
return fmt.Sprintf("Version: %d", spec.Version)
}
}

return noSpecFound
return "No version found that matches the query."
}

func (o ObjectLineage) FullDiff(vNumStart, vNumEnd int) string {
var b strings.Builder
sp1 := o[vNumStart]
sp2 := o[vNumEnd]
for attribute, data1 := range sp1.AttributeToData {
var stringSlice1, stringSlice2 string

sliceStringData1, okTypeAssertion1 := data1.([]string)
if okTypeAssertion1 {
stringSlice1 = strings.Join(sliceStringData1, " ")
}

data2, ok := sp2.AttributeToData[attribute] //check if the attribute even exists
if ok {

sliceStringData2, okTypeAssertion2 := data2.([]string) //type assertion to compare slices
if okTypeAssertion2 {
stringSlice2 = strings.Join(sliceStringData2, " ")
}

if okTypeAssertion1 && okTypeAssertion2 {
if stringSlice1 != stringSlice2 {
fmt.Fprintf(&b, "Found diff on attribute %s:\n", attribute)
fmt.Fprintf(&b, "\tVersion %d: %s\n", vNumStart, stringSlice1)
fmt.Fprintf(&b, "\tVersion %d: %s\n", vNumEnd, stringSlice2)
} else {
// fmt.Fprintf(&b, "No difference for attribute %s \n", attribute)
}
if data1 != data2 {
fmt.Fprintf(&b, "Found diff on attribute %s:\n", attribute)
fmt.Fprintf(&b, "\tVersion %d: %s\n", vNumStart, data1)
fmt.Fprintf(&b, "\tVersion %d: %s\n", vNumEnd, data2)
} else {
if data1 != data2 {
fmt.Fprintf(&b, "Found diff on attribute %s:\n", attribute)
fmt.Fprintf(&b, "\tVersion %d: %s\n", vNumStart, data1)
fmt.Fprintf(&b, "\tVersion %d: %s\n", vNumEnd, data2)
} else {
// fmt.Fprintf(&b, "No difference for attribute %s \n", attribute)
}
// fmt.Fprintf(&b, "No difference for attribute %s \n", attribute)
}

} else { //for the case where a key exists in spec 1 that doesn't exist in spec 2
fmt.Fprintf(&b, "Found diff on attribute %s:\n", attribute)
fmt.Fprintf(&b, "\tVersion %d: %s\n", vNumStart, data1)
Expand Down Expand Up @@ -419,16 +414,17 @@ func parse() {
}

requestobj := event.RequestObject
timestamp := fmt.Sprint(event.RequestReceivedTimestamp.Format("2006-01-02 15:04:05"))
//now parse the spec into this provenanceObject that we found or created
ParseRequestObject(provObjPtr, requestobj.Raw)
ParseRequestObject(provObjPtr, requestobj.Raw, timestamp)
}
if err := scanner.Err(); err != nil {
panic(err)
}
fmt.Println("Done parsing.")
}

func ParseRequestObject(objectProvenance *ProvenanceOfObject, requestObjBytes []byte) {
func ParseRequestObject(objectProvenance *ProvenanceOfObject, requestObjBytes []byte, timestamp string) {
fmt.Println("entering parse request")
var result map[string]interface{}
json.Unmarshal([]byte(requestObjBytes), &result)
Expand Down Expand Up @@ -466,11 +462,12 @@ func ParseRequestObject(objectProvenance *ProvenanceOfObject, requestObjBytes []
if ok {
fmt.Println("Successfully parsed")
} else {
fmt.Println("Unsuccessful parse")
fmt.Println("Unsuccessful parsed")
}
newVersion := len(objectProvenance.ObjectFullHistory) + 1
newSpec := buildSpec(spec)
newSpec.Version = newVersion
newSpec.Timestamp = timestamp
objectProvenance.ObjectFullHistory[newVersion] = newSpec
fmt.Println("exiting parse request")
}
Expand Down Expand Up @@ -501,32 +498,7 @@ func buildSpec(spec map[string]interface{}) Spec {
}
switch {
case isMap:
//we don't know the keys and don't know the data
//could be this for example:
//usernames = [daniel, steve, jenny]
//passwords = [22d732, 4343e2, 434343b]
attributeToSlices := make(map[string][]string, 0)
//build this and then i will loop through and add this to the spec
for _, mapl := range mapSliceField { //this is an []map[string]string

for key, data := range mapl {
slice, ok := attributeToSlices[key]
if ok {
slice = append(slice, data)
attributeToSlices[key] = slice
} else { // first time seeing this key
slice := make([]string, 0)
slice = append(slice, data)
attributeToSlices[key] = slice
}
}
}

//now add to the spec attributes
for key, value := range attributeToSlices {
mySpec.AttributeToData[key] = value
}

mySpec.AttributeToData[attribute] = mapSliceField
case isStringSlice:
mySpec.AttributeToData[attribute] = stringSliceField
case isString:
Expand Down

0 comments on commit 686773f

Please sign in to comment.