<commit_before>package iam

import (
	"fmt"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/viant/endly"
	"github.com/viant/endly/system/cloud/aws"
	"log"
)

const (
	//ServiceID aws iam service id.
	ServiceID = "aws/iam"
)

//no operation service
type service struct {
	*endly.AbstractService
}

func (s *service) dropRole(context *endly.Context, request *DropRoleInput) (interface{}, error) {
	client, err := GetClient(context)
	if err != nil {
		return nil, err
	}
	policies, err := client.ListRolePolicies(&iam.ListRolePoliciesInput{
		RoleName: request.RoleName,
	})
	if err != nil {
		return nil, err
	}
	if policies != nil && len(policies.PolicyNames) > 0 {
		for _, policy := range policies.PolicyNames {
			if _, err = client.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
				PolicyName: policy,
				RoleName:   request.RoleName,
			}); err != nil {
				return nil, fmt.Errorf("failed to delete policy %v", err)
			}
		}
	}
	output, err := client.ListAttachedRolePolicies(&iam.ListAttachedRolePoliciesInput{
		RoleName: request.RoleName,
	})
	if err != nil {
		return nil, err
	}
	if output != nil && len(output.AttachedPolicies) > 0 {
		for _, attached := range output.AttachedPolicies {
			if _, err = client.DetachRolePolicy(&iam.DetachRolePolicyInput{
				PolicyArn: attached.PolicyArn,
				RoleName:  request.RoleName,
			}); err != nil {
				return nil, fmt.Errorf("failed to detach policy %v", err)
			}
		}
	}
	return client.DeleteRole(&iam.DeleteRoleInput{
		RoleName: request.RoleName,
	})
}

func (s *service) recreateRole(context *endly.Context, request *RecreateRoleInput) (*iam.CreateRoleOutput, error) {
	client, err := GetClient(context)
	if err != nil {
		return nil, err
	}
	output, err := client.GetRole(&iam.GetRoleInput{
		RoleName: request.RoleName,
	})
	if err == nil && output.Role != nil {
		if _, err = s.dropRole(context, &DropRoleInput{
			RoleName: request.RoleName,
		}); err != nil {
			return nil, err
		}
	}
	iamRequest := iam.CreateRoleInput(*request)
	return client.CreateRole(&iamRequest)
}

func (s *service) setupRole(context *endly.Context, request *SetupRolePolicyInput) (*GetRoleInfoOutput, error) {
	client, err := GetClient(context)
	if err != nil {
		return nil, err
	}

	roleOutput, foundErr := client.GetRole(&iam.GetRoleInput{
		RoleName: request.RoleName,
	})

	var role *iam.Role
	if foundErr !=  nil{
		createRole := &request.CreateRoleInput
		if createRole.AssumeRolePolicyDocument == nil {
			createRole.AssumeRolePolicyDocument = request.DefaultPolicyDocument
		}
		created, err := client.CreateRole(createRole)
		if err != nil {
			return nil, err
		}
		role = created.Role
	} else {
		role = roleOutput.Role
		if request.AssumeRolePolicyDocument != nil {
			if _, err = client.UpdateAssumeRolePolicy(&iam.UpdateAssumeRolePolicyInput{
				PolicyDocument: request.AssumeRolePolicyDocument,
				RoleName:       request.RoleName,
			}); err != nil {
				return nil, err
			}
		}
	}



	if err = s.setupAttachedRolePolicy(context, role, request); err != nil {
		return nil, err
	}
	if err = s.setupRolePolicy(context, role, request); err != nil {
		return nil, err
	}
	return s.getRoleInfo(context, &GetRoleInfoInput{
		RoleName: request.RoleName,
	})
}

func (s *service) setupRolePolicy(context *endly.Context, role *iam.Role, request *SetupRolePolicyInput) (error) {
	client, err := GetClient(context)
	if err != nil {
		return err
	}
	if len(request.Define) == 0 {
		return err
	}
	var alreadyDefined = make(map[string]bool)
	outputList, _ := client.ListRolePolicies(&iam.ListRolePoliciesInput{
		RoleName: role.RoleName,
	})
	if outputList != nil && len(outputList.PolicyNames) > 0 {
		for _, policy := range outputList.PolicyNames {
			alreadyDefined[*policy] = true
		}
	}

	for _, define := range request.Define {
		if _, has := alreadyDefined[*define.PolicyName]; has {
			delete(alreadyDefined, *define.PolicyName)
			policy, _ := client.GetRolePolicy(&iam.GetRolePolicyInput{<commit_msg>added data substitution on policy documents<commit_after>package iam

import (
	"fmt"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/viant/endly"
	"github.com/viant/endly/system/cloud/aws"
	"log"
)

const (
	//ServiceID aws iam service id.
	ServiceID = "aws/iam"
)

//no operation service
type service struct {
	*endly.AbstractService
}

func (s *service) dropRole(context *endly.Context, request *DropRoleInput) (interface{}, error) {
	client, err := GetClient(context)
	if err != nil {
		return nil, err
	}
	policies, err := client.ListRolePolicies(&iam.ListRolePoliciesInput{
		RoleName: request.RoleName,
	})
	if err != nil {
		return nil, err
	}
	if policies != nil && len(policies.PolicyNames) > 0 {
		for _, policy := range policies.PolicyNames {
			if _, err = client.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
				PolicyName: policy,
				RoleName:   request.RoleName,
			}); err != nil {
				return nil, fmt.Errorf("failed to delete policy %v", err)
			}
		}
	}
	output, err := client.ListAttachedRolePolicies(&iam.ListAttachedRolePoliciesInput{
		RoleName: request.RoleName,
	})
	if err != nil {
		return nil, err
	}
	if output != nil && len(output.AttachedPolicies) > 0 {
		for _, attached := range output.AttachedPolicies {
			if _, err = client.DetachRolePolicy(&iam.DetachRolePolicyInput{
				PolicyArn: attached.PolicyArn,
				RoleName:  request.RoleName,
			}); err != nil {
				return nil, fmt.Errorf("failed to detach policy %v", err)
			}
		}
	}
	return client.DeleteRole(&iam.DeleteRoleInput{
		RoleName: request.RoleName,
	})
}

func (s *service) recreateRole(context *endly.Context, request *RecreateRoleInput) (*iam.CreateRoleOutput, error) {
	client, err := GetClient(context)
	if err != nil {
		return nil, err
	}
	output, err := client.GetRole(&iam.GetRoleInput{
		RoleName: request.RoleName,
	})
	if err == nil && output.Role != nil {
		if _, err = s.dropRole(context, &DropRoleInput{
			RoleName: request.RoleName,
		}); err != nil {
			return nil, err
		}
	}
	state := context.State()
	if request.AssumeRolePolicyDocument != nil {
		*request.AssumeRolePolicyDocument = state.ExpandAsText(*request.AssumeRolePolicyDocument)
	}
	iamRequest := iam.CreateRoleInput(*request)
	return client.CreateRole(&iamRequest)
}

func (s *service) setupRole(context *endly.Context, request *SetupRolePolicyInput) (*GetRoleInfoOutput, error) {
	client, err := GetClient(context)
	if err != nil {
		return nil, err
	}

	roleOutput, foundErr := client.GetRole(&iam.GetRoleInput{
		RoleName: request.RoleName,
	})

	state := context.State()
	var role *iam.Role
	if foundErr !=  nil{
		createRole := &request.CreateRoleInput
		if createRole.AssumeRolePolicyDocument == nil {
			createRole.AssumeRolePolicyDocument = request.DefaultPolicyDocument
		}

		if request.AssumeRolePolicyDocument != nil {
			*request.AssumeRolePolicyDocument = state.ExpandAsText(*request.AssumeRolePolicyDocument)
		}

		created, err := client.CreateRole(createRole)
		if err != nil {
			return nil, err
		}
		role = created.Role
	} else {
		role = roleOutput.Role
		if request.AssumeRolePolicyDocument != nil {
			if _, err = client.UpdateAssumeRolePolicy(&iam.UpdateAssumeRolePolicyInput{
				PolicyDocument: request.AssumeRolePolicyDocument,
				RoleName:       request.RoleName,
			}); err != nil {
				return nil, err
			}
		}
	}



	if err = s.setupAttachedRolePolicy(context, role, request); err != nil {
		return nil, err
	}
	if err = s.setupRolePolicy(context, role, request); err != nil {
		return nil, err
	}
	return s.getRoleInfo(context, &GetRoleInfoInput{
		RoleName: request.RoleName,
	})
}

func (s *service) setupRolePolicy(context *endly.Context, role *iam.Role, request *SetupRolePolicyInput) (error) {
	client, err := GetClient(context)
	if err != nil {
		return err
	}
	state := context.State()
	if len(request.Define) == 0 {
		return err
	}
	var alreadyDefined = make(map[string]bool)
	outputList, _ := client.ListRolePolicies(&iam.ListRolePoliciesInput{
		RoleName: role.RoleName,
	})
	if outputList != nil && len(outputList.PolicyNames) > 0 {
		for _, policy := range outputList.PolicyNames {
			alreadyDefined[*policy] = true
		}
	}

	for _, define := range request.Define {
		*define.PolicyDocument = state.ExpandAsText(*define.PolicyDocument)

		if _, has := alreadyDefined[*define.PolicyName]; has {
			delete(alreadyDefined, *define.PolicyName)
			policy, _ := client.GetRolePolicy(&iam.GetRolePolicyInput{
{'fraction_non_alphanumeric': 0.12741358760429083, 'fraction_numerical': 0.0009535160905840286, 'mean_word_length': 4.163692307692307, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2953075', 'n_tokens_mistral': 3024, 'n_tokens_neox': 2784, 'n_words': 632}