Skip to content

Commit

Permalink
Merge pull request #68 from atlanhq/FT-806-manage-personas
Browse files Browse the repository at this point in the history
FT-806: Manage Personas
  • Loading branch information
0xquark authored Dec 5, 2024
2 parents 678adeb + 979a2f9 commit f1eed6d
Show file tree
Hide file tree
Showing 12 changed files with 1,767 additions and 166 deletions.
249 changes: 248 additions & 1 deletion atlan/assets/asset.go

Large diffs are not rendered by default.

152 changes: 152 additions & 0 deletions atlan/assets/auth_policy_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package assets

import (
"encoding/json"
"errors"
"github.com/atlanhq/atlan-go/atlan"
"github.com/atlanhq/atlan-go/atlan/model/structs"
)

type AuthPolicy structs.AuthPolicy

func (a *AuthPolicy) Updater(name string, qualifiedName string) error {
if name == "" || qualifiedName == "" {
return errors.New("name, qualifiedName are required fields")
}

a.Name = &name
a.QualifiedName = &qualifiedName

return nil
}

func (a *AuthPolicy) UnmarshalJSON(data []byte) error {
// Define a temporary structure with the expected JSON structure.
var temp struct {
ReferredEntities map[string]interface{} `json:"referredEntities"`
Entity struct {
TypeName string `json:"typeName"`
AttributesJSON json.RawMessage `json:"attributes"`
Guid string `json:"guid"`
IsIncomplete bool `json:"isIncomplete"`
Status atlan.AtlanStatus `json:"status"`
CreatedBy string `json:"createdBy"`
UpdatedBy string `json:"updatedBy"`
CreateTime int64 `json:"createTime"`
UpdateTime int64 `json:"updateTime"`
Version int `json:"version"`
RelationshipAttributes struct {
SchemaRegistrySubjects []structs.SchemaRegistrySubject `json:"schemaRegistrySubjects"`
McMonitors []structs.MCMonitor `json:"mcMonitors"`
Terms []structs.AtlasGlossaryTerm `json:"terms"`
OutputPortDataProducts []string `json:"outputPortDataProducts"`
AtlasGlossary []structs.AtlasGlossary `json:"AtlasGlossary"`
AccessControl []structs.AccessControl `json:"AccessControl"`
Policies []structs.AuthPolicy `json:"policies"`
} `json:"relationshipAttributes"`
}
}

// Unmarshal the JSON data into the temporary structure.
if err := json.Unmarshal(data, &temp); err != nil {
return err
}

// Unmarshal the attributes JSON into the entity.
if err := json.Unmarshal(temp.Entity.AttributesJSON, &a); err != nil {
return err
}

// Set the GUID and TypeName.
a.Guid = &temp.Entity.Guid
a.TypeName = &temp.Entity.TypeName

return nil
}

func (a *AuthPolicy) MarshalJSON() ([]byte, error) {
// Marshal the AccessControl asset into a JSON object.

// Construct the custom JSON structure
customJSON := map[string]interface{}{
"typeName": "AuthPolicy",
"attributes": map[string]interface{}{
"name": a.Name,
"qualifiedName": a.Name,
// Add other attributes as necessary.
},
}

attributes := customJSON["attributes"].(map[string]interface{})

if a.QualifiedName != nil && *a.QualifiedName != "" {
attributes["qualifiedName"] = *a.QualifiedName
}

// if a.Guid != nil && *a.Guid != "" {
// customJSON["guid"] = *a.Guid
// }

if a.DisplayName != nil && *a.DisplayName != "" {
attributes["displayName"] = *a.DisplayName
}

if a.PolicyType != nil {
attributes["policyType"] = *a.PolicyType
}

if a.PolicyCategory != nil && *a.PolicyCategory != "" {
attributes["policyCategory"] = *a.PolicyCategory
}

if a.PolicyResources != nil {
attributes["policyResources"] = *a.PolicyResources
}

if a.PolicyActions != nil {
attributes["policyActions"] = *a.PolicyActions
}

if a.PolicyResourceCategory != nil && *a.PolicyResourceCategory != "" {
attributes["policyResourceCategory"] = *a.PolicyResourceCategory
}

if a.PolicyServiceName != nil && *a.PolicyServiceName != "" {
attributes["policyServiceName"] = *a.PolicyServiceName
}

if a.PolicySubCategory != nil && *a.PolicySubCategory != "" {
attributes["policySubCategory"] = *a.PolicySubCategory
}

if a.ConnectionQualifiedName != nil && *a.ConnectionQualifiedName != "" {
attributes["connectionQualifiedName"] = *a.ConnectionQualifiedName
}

// Handle nested AccessControl field
if a.AccessControl != nil {
accessControl := map[string]interface{}{}

if a.AccessControl.Guid != nil && *a.AccessControl.Guid != "" {
accessControl["guid"] = *a.AccessControl.Guid
}

if a.AccessControl.TypeName != nil && *a.AccessControl.TypeName != "" {
accessControl["typeName"] = *a.AccessControl.TypeName
}

attributes["accessControl"] = accessControl
}

return json.MarshalIndent(customJSON, "", " ")
}

func (a *AuthPolicy) ToJSON() ([]byte, error) {
// Marshal the Persona object into a JSON object.
return json.Marshal(a)
}

func (a *AuthPolicy) FromJSON(data []byte) error {
// Unmarshal the JSON data into the Persona object.
return json.Unmarshal(data, a)
}
16 changes: 16 additions & 0 deletions atlan/assets/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ func newDefaultSearchAssets() SearchAssets {
Connection: NewSearchConnection(),
MaterialisedView: NewSearchMaterialisedView(),
View: NewSearchView(),
Persona: NewPersonaFields(),
AccessControl: NewAccessControlFields(),
AuthPolicy: NewAuthPolicyFields(),
}
}

Expand Down Expand Up @@ -457,6 +460,19 @@ func (ac *AtlanClient) CallAPI(api *API, queryParams interface{}, requestObj int

// Handle API error based on response status code
if response.StatusCode != api.Status {
body, readErr := io.ReadAll(response.Body)
if readErr != nil {
fmt.Printf("Error reading response body: %v\n", readErr)
return nil, handleApiError(response, fmt.Errorf("error reading response body: %v", readErr))
}

// Create a descriptive error if `err` is nil
var errorMessage string
if err == nil {
errorMessage = fmt.Sprintf("API returned status code %d: %s", response.StatusCode, string(body))
err = fmt.Errorf(errorMessage)
// fmt.Printf("Constructed error: %s\n", errorMessage) // Optional for debugging
}
return nil, handleApiError(response, err)
}

Expand Down
146 changes: 61 additions & 85 deletions atlan/assets/glossary_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,130 +17,106 @@ const (
type AtlasGlossary structs.AtlasGlossary

// Creator is used to create a new glossary asset in memory.
func (g *AtlasGlossary) Creator(name string, icon atlan.AtlanIcon) {
g.TypeName = structs.StringPtr("AtlasGlossary")
g.Name = structs.StringPtr(name)
g.QualifiedName = structs.StringPtr(name)
g.AssetIcon = atlan.AtlanIconPtr(icon)
func (ag *AtlasGlossary) Creator(name string, icon atlan.AtlanIcon) {
ag.TypeName = structs.StringPtr("AtlasGlossary")
ag.Name = structs.StringPtr(name)
ag.QualifiedName = structs.StringPtr(name)
ag.AssetIcon = atlan.AtlanIconPtr(icon)
}

// Updater is used to modify a glossary asset in memory.
func (g *AtlasGlossary) Updater(name string, qualifiedName string, glossary_guid string) error {
func (ag *AtlasGlossary) Updater(name string, qualifiedName string, glossary_guid string) error {
if name == "" || qualifiedName == "" || glossary_guid == "" {
return errors.New("name, qualified_name, and glossary_guid are required fields")
}

g.TypeName = structs.StringPtr("AtlasGlossary")
g.Name = structs.StringPtr(name)
g.Guid = structs.StringPtr(glossary_guid)
g.QualifiedName = structs.StringPtr(qualifiedName)
ag.TypeName = structs.StringPtr("AtlasGlossary")
ag.Name = structs.StringPtr(name)
ag.Guid = structs.StringPtr(glossary_guid)
ag.QualifiedName = structs.StringPtr(qualifiedName)

return nil
}

func (ag *AtlasGlossary) UnmarshalJSON(data []byte) error {
// Define a temporary structure with the expected JSON structure.
var temp struct {
ReferredEntities map[string]interface{} `json:"referredEntities"`
Entity struct {
TypeName string `json:"typeName"`
AttributesJSON json.RawMessage `json:"attributes"`
Guid string `json:"guid"`
IsIncomplete bool `json:"isIncomplete"`
Status atlan.AtlanStatus `json:"status"`
CreatedBy string `json:"createdBy"`
UpdatedBy string `json:"updatedBy"`
CreateTime int64 `json:"createTime"`
UpdateTime int64 `json:"updateTime"`
Version int `json:"version"`
RelationshipAttributes struct {
SchemaRegistrySubjects []structs.SchemaRegistrySubject `json:"schemaRegistrySubjects"`
McMonitors []structs.MCMonitor `json:"mcMonitors"`
Terms []structs.AtlasGlossaryTerm `json:"terms"`
OutputPortDataProducts []string `json:"outputPortDataProducts"`
Files []structs.File `json:"files"`
McIncidents []structs.MCIncident `json:"mcIncidents"`
Links []structs.Link `json:"links"`
Categories []structs.AtlasGlossaryCategory `json:"categories"`
Metrics []structs.Metric `json:"metrics"`
Readme []structs.Readme `json:"readme"`
Meanings []structs.Meaning `json:"meanings"`
SodaChecks []structs.SodaCheck `json:"sodaChecks"`
} `json:"relationshipAttributes"`
Labels []interface{} `json:"labels"`
} `json:"entity"`
}

// Unmarshal the JSON into the temporary structure
if err := json.Unmarshal(data, &temp); err != nil {
Attributes := struct {
Name *string `json:"name"`
QualifiedName *string `json:"qualifiedName"`
AssetIcon *atlan.AtlanIcon `json:"assetIcon"`
ShortDescription *string `json:"shortDescription"`
LongDescription *string `json:"longDescription"`
Language *string `json:"language"`
Usage *string `json:"usage"`
// Add other attributes as necessary.
}{}

base, err := UnmarshalBaseEntity(data, &Attributes)
if err != nil {
return err
}

// Map the fields from the temporary structure to your AtlasGlossary struct
ag.TypeName = &temp.Entity.TypeName
ag.Guid = &temp.Entity.Guid
ag.IsIncomplete = &temp.Entity.IsIncomplete
ag.Status = &temp.Entity.Status
ag.CreatedBy = &temp.Entity.CreatedBy
ag.UpdatedBy = &temp.Entity.UpdatedBy
ag.CreateTime = &temp.Entity.CreateTime
ag.UpdateTime = &temp.Entity.UpdateTime

var asset structs.AtlasGlossaryAttributes
if err := json.Unmarshal(temp.Entity.AttributesJSON, &asset); err != nil {
return err
}

// Map Asset fields
ag.Name = asset.Name
ag.AssetIcon = asset.AssetIcon
ag.QualifiedName = asset.QualifiedName
ag.ShortDescription = asset.ShortDescription
ag.LongDescription = asset.LongDescription
ag.Language = asset.Language
ag.Usage = asset.Usage
ag.AssetIcon = asset.AssetIcon
// Map Shared Fields
ag.TypeName = &base.Entity.TypeName
ag.Guid = &base.Entity.Guid
ag.IsIncomplete = &base.Entity.IsIncomplete
ag.Status = &base.Entity.Status
ag.CreatedBy = &base.Entity.CreatedBy
ag.UpdatedBy = &base.Entity.UpdatedBy
ag.CreateTime = &base.Entity.CreateTime
ag.UpdateTime = &base.Entity.UpdateTime

// Map Attribute fields
ag.Name = Attributes.Name
ag.QualifiedName = Attributes.QualifiedName
ag.ShortDescription = Attributes.ShortDescription
ag.LongDescription = Attributes.LongDescription
ag.Language = Attributes.Language
ag.Usage = Attributes.Usage
ag.AssetIcon = Attributes.AssetIcon

return nil
}

// MarshalJSON filters out entities to only include those with non-empty attributes.
func (g *AtlasGlossary) MarshalJSON() ([]byte, error) {
func (ag *AtlasGlossary) MarshalJSON() ([]byte, error) {
// Construct the custom JSON structure
customJSON := map[string]interface{}{
"typeName": "AtlasGlossary",
"attributes": map[string]interface{}{
"name": g.Name,
"name": ag.Name,
// Add other attributes as necessary.
},
"relationshipAttributes": make(map[string]interface{}),
}

if g.QualifiedName != nil && *g.QualifiedName != "" {
customJSON["attributes"].(map[string]interface{})["qualifiedName"] = *g.QualifiedName
attributes := customJSON["attributes"].(map[string]interface{})

if ag.QualifiedName != nil && *ag.QualifiedName != "" {
attributes["qualifiedName"] = *ag.QualifiedName
}

if g.Guid != nil && *g.Guid != "" {
customJSON["guid"] = *g.Guid
if ag.Guid != nil && *ag.Guid != "" {
customJSON["guid"] = *ag.Guid
}

if g.DisplayName != nil && *g.DisplayName != "" {
customJSON["attributes"].(map[string]interface{})["displayName"] = *g.DisplayName
if ag.DisplayName != nil && *ag.DisplayName != "" {
attributes["displayName"] = *ag.DisplayName
}
if g.Description != nil && *g.Description != "" {
customJSON["attributes"].(map[string]interface{})["description"] = *g.Description
if ag.Description != nil && *ag.Description != "" {
attributes["description"] = *ag.Description
}
if g.AnnouncementType != nil {
customJSON["attributes"].(map[string]interface{})["announcementType"] = *g.AnnouncementType
if ag.AnnouncementType != nil {
attributes["announcementType"] = *ag.AnnouncementType
}
if g.AnnouncementTitle != nil && *g.AnnouncementTitle != "" {
customJSON["attributes"].(map[string]interface{})["announcementTitle"] = *g.AnnouncementTitle
if ag.AnnouncementTitle != nil && *ag.AnnouncementTitle != "" {
attributes["announcementTitle"] = *ag.AnnouncementTitle
}
if g.AnnouncementMessage != nil && *g.AnnouncementMessage != "" {
customJSON["attributes"].(map[string]interface{})["announcementMessage"] = *g.AnnouncementMessage
if ag.AnnouncementMessage != nil && *ag.AnnouncementMessage != "" {
attributes["announcementMessage"] = *ag.AnnouncementMessage
}
if g.CertificateStatus != nil {
customJSON["attributes"].(map[string]interface{})["certificateStatus"] = *g.CertificateStatus
if ag.CertificateStatus != nil {
attributes["certificateStatus"] = *ag.CertificateStatus
}

// Marshal the custom JSON
Expand Down
Loading

0 comments on commit f1eed6d

Please sign in to comment.