func()

in pkg/source/gcp/task/gke/gke_audit/parser.go [66:185]


func (p *gkeAuditLogParser) Parse(ctx context.Context, l *log.LogEntity, cs *history.ChangeSet, builder *history.Builder) error {
	clusterName := l.GetStringOrDefault("resource.labels.cluster_name", "unknown")
	isFirst := l.Has("operation.first")
	isLast := l.Has("operation.last")
	operationId := l.GetStringOrDefault("operation.id", "unknown")
	methodName := l.GetStringOrDefault("protoPayload.methodName", "unknown")
	principal := l.GetStringOrDefault("protoPayload.authenticationInfo.principalEmail", "unknown")
	statusCode := l.GetIntOrDefault("protoPayload.status.code", 0)
	shouldRecordResourceRevision := statusCode == 0
	var operationResourcePath resourcepath.ResourcePath

	nodepoolName, err := getRelatedNodepool(l)
	if err != nil {
		// assume this is a cluster operation
		clusterResourcePath := resourcepath.Cluster(clusterName)
		if shouldRecordResourceRevision {
			if strings.HasSuffix(methodName, "CreateCluster") {
				body, _ := l.GetChildYamlOf("protoPayload.request.cluster") // Ignore the error and use "" as the body of the cluster setting when the field is not available.
				state := enum.RevisionStateExisting
				if isFirst {
					state = enum.RevisionStateProvisioning
				}
				cs.RecordRevision(clusterResourcePath, &history.StagingResourceRevision{
					Verb:       enum.RevisionVerbCreate,
					State:      state,
					Requestor:  principal,
					ChangeTime: l.Timestamp(),
					Partial:    false,
					Body:       body,
				})
			}
			if strings.HasSuffix(methodName, "DeleteCluster") {
				state := enum.RevisionStateDeleted
				if isFirst {
					state = enum.RevisionStateDeleting
				}
				cs.RecordRevision(clusterResourcePath, &history.StagingResourceRevision{
					Verb:       enum.RevisionVerbDelete,
					State:      state,
					Requestor:  principal,
					ChangeTime: l.Timestamp(),
					Partial:    false,
					Body:       "",
				})
			}
		}

		methodNameSplitted := strings.Split(methodName, ".")
		methodVerb := methodNameSplitted[len(methodNameSplitted)-1]
		operationResourcePath = resourcepath.Operation(clusterResourcePath, methodVerb, operationId)

		cs.RecordEvent(clusterResourcePath)
	} else {
		nodepoolResourcePath := resourcepath.Nodepool(clusterName, nodepoolName)
		if shouldRecordResourceRevision {
			if strings.HasSuffix(methodName, "CreateNodePool") {
				body, _ := l.GetChildYamlOf("protoPayload.request.nodePool") // Ignore the error and use "" as the body of the nodepool setting when the field is not available.
				state := enum.RevisionStateExisting
				if isFirst {
					state = enum.RevisionStateProvisioning
				}
				cs.RecordRevision(nodepoolResourcePath, &history.StagingResourceRevision{
					Verb:       enum.RevisionVerbCreate,
					State:      state,
					Requestor:  principal,
					ChangeTime: l.Timestamp(),
					Partial:    false,
					Body:       body,
				})
			}
			if strings.HasSuffix(methodName, "DeleteNodePool") {
				state := enum.RevisionStateDeleted
				if isFirst {
					state = enum.RevisionStateDeleting
				}
				cs.RecordRevision(nodepoolResourcePath, &history.StagingResourceRevision{
					Verb:       enum.RevisionVerbDelete,
					State:      state,
					Requestor:  principal,
					ChangeTime: l.Timestamp(),
					Partial:    false,
					Body:       "",
				})
			}
		}
		cs.RecordEvent(nodepoolResourcePath)
		methodNameSplitted := strings.Split(methodName, ".")
		methodVerb := methodNameSplitted[len(methodNameSplitted)-1]
		operationResourcePath = resourcepath.Operation(nodepoolResourcePath, methodVerb, operationId)
	}

	// If this was an operation, it will be recorded as operation data
	if !(isLast && isFirst) && (isLast || isFirst) && shouldRecordResourceRevision {
		requestBody, _ := l.GetChildYamlOf("protoPayload.request") // ignore the error to set the empty body when the field is not available in the log.
		state := enum.RevisionStateOperationStarted
		verb := enum.RevisionVerbOperationStart
		if isLast {
			state = enum.RevisionStateOperationFinished
			verb = enum.RevisionVerbOperationFinish
		}
		cs.RecordRevision(operationResourcePath, &history.StagingResourceRevision{
			Verb:       verb,
			State:      state,
			Requestor:  principal,
			ChangeTime: l.Timestamp(),
			Partial:    false,
			Body:       requestBody,
		})
	}

	switch {
	case isFirst && !isLast:
		cs.RecordLogSummary(fmt.Sprintf("%s Started", methodName))
	case !isFirst && isLast:
		cs.RecordLogSummary(fmt.Sprintf("%s Finished", methodName))
	default:
		cs.RecordLogSummary(methodName)
	}
	return nil
}