text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: sso_admin
using AWS.Compat
using AWS.UUIDs

"""
    attach_managed_policy_to_permission_set(instance_arn, managed_policy_arn, permission_set_arn)
    attach_managed_policy_to_permission_set(instance_arn, managed_policy_arn, permission_set_arn, params::Dict{String,<:Any})

Attaches an IAM managed policy ARN to a permission set.  If the permission set is already
referenced by one or more account assignments, you will need to call
ProvisionPermissionSet  after this operation. Calling ProvisionPermissionSet applies the
corresponding IAM policy updates to all assigned accounts.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `managed_policy_arn`: The IAM managed policy ARN to be attached to a permission set.
- `permission_set_arn`: The ARN of the PermissionSet that the managed policy should be
  attached to.

"""
function attach_managed_policy_to_permission_set(
    InstanceArn,
    ManagedPolicyArn,
    PermissionSetArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "AttachManagedPolicyToPermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn,
            "ManagedPolicyArn" => ManagedPolicyArn,
            "PermissionSetArn" => PermissionSetArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function attach_managed_policy_to_permission_set(
    InstanceArn,
    ManagedPolicyArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "AttachManagedPolicyToPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "ManagedPolicyArn" => ManagedPolicyArn,
                    "PermissionSetArn" => PermissionSetArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_account_assignment(instance_arn, permission_set_arn, principal_id, principal_type, target_id, target_type)
    create_account_assignment(instance_arn, permission_set_arn, principal_id, principal_type, target_id, target_type, params::Dict{String,<:Any})

Assigns access to a principal for a specified Amazon Web Services account using a specified
permission set.  The term principal here refers to a user or group that is defined in
Amazon Web Services SSO.   As part of a successful CreateAccountAssignment call, the
specified permission set will automatically be provisioned to the account in the form of an
IAM policy. That policy is attached to the SSO-created IAM role. If the permission set is
subsequently updated, the corresponding IAM policies attached to roles in your accounts
will not be updated automatically. In this case, you must call  ProvisionPermissionSet  to
make these updates.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set that the admin wants to grant the
  principal access to.
- `principal_id`: An identifier for an object in Amazon Web Services SSO, such as a user or
  group. PrincipalIds are GUIDs (For example, f81d4fae-7dec-11d0-a765-00a0c91e6bf6). For more
  information about PrincipalIds in Amazon Web Services SSO, see the Amazon Web Services SSO
  Identity Store API Reference.
- `principal_type`: The entity type for which the assignment will be created.
- `target_id`: TargetID is an Amazon Web Services account identifier, typically a 10-12
  digit string (For example, 123456789012).
- `target_type`: The entity type for which the assignment will be created.

"""
function create_account_assignment(
    InstanceArn,
    PermissionSetArn,
    PrincipalId,
    PrincipalType,
    TargetId,
    TargetType;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "CreateAccountAssignment",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn,
            "PermissionSetArn" => PermissionSetArn,
            "PrincipalId" => PrincipalId,
            "PrincipalType" => PrincipalType,
            "TargetId" => TargetId,
            "TargetType" => TargetType,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_account_assignment(
    InstanceArn,
    PermissionSetArn,
    PrincipalId,
    PrincipalType,
    TargetId,
    TargetType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "CreateAccountAssignment",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "PermissionSetArn" => PermissionSetArn,
                    "PrincipalId" => PrincipalId,
                    "PrincipalType" => PrincipalType,
                    "TargetId" => TargetId,
                    "TargetType" => TargetType,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_instance_access_control_attribute_configuration(instance_access_control_attribute_configuration, instance_arn)
    create_instance_access_control_attribute_configuration(instance_access_control_attribute_configuration, instance_arn, params::Dict{String,<:Any})

Enables the attributes-based access control (ABAC) feature for the specified Amazon Web
Services SSO instance. You can also specify new attributes to add to your ABAC
configuration during the enabling process. For more information about ABAC, see
Attribute-Based Access Control in the Amazon Web Services SSO User Guide.

# Arguments
- `instance_access_control_attribute_configuration`: Specifies the Amazon Web Services SSO
  identity store attributes to add to your ABAC configuration. When using an external
  identity provider as an identity source, you can pass attributes through the SAML
  assertion. Doing so provides an alternative to configuring attributes from the Amazon Web
  Services SSO identity store. If a SAML assertion passes any of these attributes, Amazon Web
  Services SSO will replace the attribute value with the value from the Amazon Web Services
  SSO identity store.
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.

"""
function create_instance_access_control_attribute_configuration(
    InstanceAccessControlAttributeConfiguration,
    InstanceArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "CreateInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}(
            "InstanceAccessControlAttributeConfiguration" =>
                InstanceAccessControlAttributeConfiguration,
            "InstanceArn" => InstanceArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_instance_access_control_attribute_configuration(
    InstanceAccessControlAttributeConfiguration,
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "CreateInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceAccessControlAttributeConfiguration" =>
                        InstanceAccessControlAttributeConfiguration,
                    "InstanceArn" => InstanceArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_permission_set(instance_arn, name)
    create_permission_set(instance_arn, name, params::Dict{String,<:Any})

Creates a permission set within a specified SSO instance.  To grant users and groups access
to Amazon Web Services account resources, use  CreateAccountAssignment .

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `name`: The name of the PermissionSet.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: The description of the PermissionSet.
- `"RelayState"`: Used to redirect users within the application during the federation
  authentication process.
- `"SessionDuration"`: The length of time that the application user sessions are valid in
  the ISO-8601 standard.
- `"Tags"`: The tags to attach to the new PermissionSet.
"""
function create_permission_set(
    InstanceArn, Name; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "CreatePermissionSet",
        Dict{String,Any}("InstanceArn" => InstanceArn, "Name" => Name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_permission_set(
    InstanceArn,
    Name,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "CreatePermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("InstanceArn" => InstanceArn, "Name" => Name),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_account_assignment(instance_arn, permission_set_arn, principal_id, principal_type, target_id, target_type)
    delete_account_assignment(instance_arn, permission_set_arn, principal_id, principal_type, target_id, target_type, params::Dict{String,<:Any})

Deletes a principal's access from a specified Amazon Web Services account using a specified
permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set that will be used to remove access.
- `principal_id`: An identifier for an object in Amazon Web Services SSO, such as a user or
  group. PrincipalIds are GUIDs (For example, f81d4fae-7dec-11d0-a765-00a0c91e6bf6). For more
  information about PrincipalIds in Amazon Web Services SSO, see the Amazon Web Services SSO
  Identity Store API Reference.
- `principal_type`: The entity type for which the assignment will be deleted.
- `target_id`: TargetID is an Amazon Web Services account identifier, typically a 10-12
  digit string (For example, 123456789012).
- `target_type`: The entity type for which the assignment will be deleted.

"""
function delete_account_assignment(
    InstanceArn,
    PermissionSetArn,
    PrincipalId,
    PrincipalType,
    TargetId,
    TargetType;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DeleteAccountAssignment",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn,
            "PermissionSetArn" => PermissionSetArn,
            "PrincipalId" => PrincipalId,
            "PrincipalType" => PrincipalType,
            "TargetId" => TargetId,
            "TargetType" => TargetType,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_account_assignment(
    InstanceArn,
    PermissionSetArn,
    PrincipalId,
    PrincipalType,
    TargetId,
    TargetType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DeleteAccountAssignment",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "PermissionSetArn" => PermissionSetArn,
                    "PrincipalId" => PrincipalId,
                    "PrincipalType" => PrincipalType,
                    "TargetId" => TargetId,
                    "TargetType" => TargetType,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_inline_policy_from_permission_set(instance_arn, permission_set_arn)
    delete_inline_policy_from_permission_set(instance_arn, permission_set_arn, params::Dict{String,<:Any})

Deletes the inline policy from a specified permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set that will be used to remove access.

"""
function delete_inline_policy_from_permission_set(
    InstanceArn, PermissionSetArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "DeleteInlinePolicyFromPermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_inline_policy_from_permission_set(
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DeleteInlinePolicyFromPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_instance_access_control_attribute_configuration(instance_arn)
    delete_instance_access_control_attribute_configuration(instance_arn, params::Dict{String,<:Any})

Disables the attributes-based access control (ABAC) feature for the specified Amazon Web
Services SSO instance and deletes all of the attribute mappings that have been configured.
Once deleted, any attributes that are received from an identity source and any custom
attributes you have previously configured will not be passed. For more information about
ABAC, see Attribute-Based Access Control in the Amazon Web Services SSO User Guide.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.

"""
function delete_instance_access_control_attribute_configuration(
    InstanceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "DeleteInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}("InstanceArn" => InstanceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_instance_access_control_attribute_configuration(
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DeleteInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("InstanceArn" => InstanceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_permission_set(instance_arn, permission_set_arn)
    delete_permission_set(instance_arn, permission_set_arn, params::Dict{String,<:Any})

Deletes the specified permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set that should be deleted.

"""
function delete_permission_set(
    InstanceArn, PermissionSetArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "DeletePermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_permission_set(
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DeletePermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_account_assignment_creation_status(account_assignment_creation_request_id, instance_arn)
    describe_account_assignment_creation_status(account_assignment_creation_request_id, instance_arn, params::Dict{String,<:Any})

Describes the status of the assignment creation request.

# Arguments
- `account_assignment_creation_request_id`: The identifier that is used to track the
  request operation progress.
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.

"""
function describe_account_assignment_creation_status(
    AccountAssignmentCreationRequestId,
    InstanceArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribeAccountAssignmentCreationStatus",
        Dict{String,Any}(
            "AccountAssignmentCreationRequestId" => AccountAssignmentCreationRequestId,
            "InstanceArn" => InstanceArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_account_assignment_creation_status(
    AccountAssignmentCreationRequestId,
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribeAccountAssignmentCreationStatus",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "AccountAssignmentCreationRequestId" =>
                        AccountAssignmentCreationRequestId,
                    "InstanceArn" => InstanceArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_account_assignment_deletion_status(account_assignment_deletion_request_id, instance_arn)
    describe_account_assignment_deletion_status(account_assignment_deletion_request_id, instance_arn, params::Dict{String,<:Any})

Describes the status of the assignment deletion request.

# Arguments
- `account_assignment_deletion_request_id`: The identifier that is used to track the
  request operation progress.
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.

"""
function describe_account_assignment_deletion_status(
    AccountAssignmentDeletionRequestId,
    InstanceArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribeAccountAssignmentDeletionStatus",
        Dict{String,Any}(
            "AccountAssignmentDeletionRequestId" => AccountAssignmentDeletionRequestId,
            "InstanceArn" => InstanceArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_account_assignment_deletion_status(
    AccountAssignmentDeletionRequestId,
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribeAccountAssignmentDeletionStatus",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "AccountAssignmentDeletionRequestId" =>
                        AccountAssignmentDeletionRequestId,
                    "InstanceArn" => InstanceArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_instance_access_control_attribute_configuration(instance_arn)
    describe_instance_access_control_attribute_configuration(instance_arn, params::Dict{String,<:Any})

Returns the list of Amazon Web Services SSO identity store attributes that have been
configured to work with attributes-based access control (ABAC) for the specified Amazon Web
Services SSO instance. This will not return attributes configured and sent by an external
identity provider. For more information about ABAC, see Attribute-Based Access Control in
the Amazon Web Services SSO User Guide.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.

"""
function describe_instance_access_control_attribute_configuration(
    InstanceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "DescribeInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}("InstanceArn" => InstanceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_instance_access_control_attribute_configuration(
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribeInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("InstanceArn" => InstanceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_permission_set(instance_arn, permission_set_arn)
    describe_permission_set(instance_arn, permission_set_arn, params::Dict{String,<:Any})

Gets the details of the permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set.

"""
function describe_permission_set(
    InstanceArn, PermissionSetArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "DescribePermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_permission_set(
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribePermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    describe_permission_set_provisioning_status(instance_arn, provision_permission_set_request_id)
    describe_permission_set_provisioning_status(instance_arn, provision_permission_set_request_id, params::Dict{String,<:Any})

Describes the status for the given permission set provisioning request.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `provision_permission_set_request_id`: The identifier that is provided by the
  ProvisionPermissionSet call to retrieve the current status of the provisioning workflow.

"""
function describe_permission_set_provisioning_status(
    InstanceArn,
    ProvisionPermissionSetRequestId;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribePermissionSetProvisioningStatus",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn,
            "ProvisionPermissionSetRequestId" => ProvisionPermissionSetRequestId,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_permission_set_provisioning_status(
    InstanceArn,
    ProvisionPermissionSetRequestId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DescribePermissionSetProvisioningStatus",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "ProvisionPermissionSetRequestId" => ProvisionPermissionSetRequestId,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    detach_managed_policy_from_permission_set(instance_arn, managed_policy_arn, permission_set_arn)
    detach_managed_policy_from_permission_set(instance_arn, managed_policy_arn, permission_set_arn, params::Dict{String,<:Any})

Detaches the attached IAM managed policy ARN from the specified permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `managed_policy_arn`: The IAM managed policy ARN to be attached to a permission set.
- `permission_set_arn`: The ARN of the PermissionSet from which the policy should be
  detached.

"""
function detach_managed_policy_from_permission_set(
    InstanceArn,
    ManagedPolicyArn,
    PermissionSetArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DetachManagedPolicyFromPermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn,
            "ManagedPolicyArn" => ManagedPolicyArn,
            "PermissionSetArn" => PermissionSetArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function detach_managed_policy_from_permission_set(
    InstanceArn,
    ManagedPolicyArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "DetachManagedPolicyFromPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "ManagedPolicyArn" => ManagedPolicyArn,
                    "PermissionSetArn" => PermissionSetArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_inline_policy_for_permission_set(instance_arn, permission_set_arn)
    get_inline_policy_for_permission_set(instance_arn, permission_set_arn, params::Dict{String,<:Any})

Obtains the inline policy assigned to the permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set.

"""
function get_inline_policy_for_permission_set(
    InstanceArn, PermissionSetArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "GetInlinePolicyForPermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_inline_policy_for_permission_set(
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "GetInlinePolicyForPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_account_assignment_creation_status(instance_arn)
    list_account_assignment_creation_status(instance_arn, params::Dict{String,<:Any})

Lists the status of the Amazon Web Services account assignment creation requests for a
specified SSO instance.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filter"`: Filters results based on the passed attribute value.
- `"MaxResults"`: The maximum number of results to display for the assignment.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_account_assignment_creation_status(
    InstanceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListAccountAssignmentCreationStatus",
        Dict{String,Any}("InstanceArn" => InstanceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_account_assignment_creation_status(
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListAccountAssignmentCreationStatus",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("InstanceArn" => InstanceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_account_assignment_deletion_status(instance_arn)
    list_account_assignment_deletion_status(instance_arn, params::Dict{String,<:Any})

Lists the status of the Amazon Web Services account assignment deletion requests for a
specified SSO instance.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filter"`: Filters results based on the passed attribute value.
- `"MaxResults"`: The maximum number of results to display for the assignment.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_account_assignment_deletion_status(
    InstanceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListAccountAssignmentDeletionStatus",
        Dict{String,Any}("InstanceArn" => InstanceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_account_assignment_deletion_status(
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListAccountAssignmentDeletionStatus",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("InstanceArn" => InstanceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_account_assignments(account_id, instance_arn, permission_set_arn)
    list_account_assignments(account_id, instance_arn, permission_set_arn, params::Dict{String,<:Any})

Lists the assignee of the specified Amazon Web Services account with the specified
permission set.

# Arguments
- `account_id`: The identifier of the Amazon Web Services account from which to list the
  assignments.
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set from which to list assignments.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to display for the assignment.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_account_assignments(
    AccountId,
    InstanceArn,
    PermissionSetArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListAccountAssignments",
        Dict{String,Any}(
            "AccountId" => AccountId,
            "InstanceArn" => InstanceArn,
            "PermissionSetArn" => PermissionSetArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_account_assignments(
    AccountId,
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListAccountAssignments",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "AccountId" => AccountId,
                    "InstanceArn" => InstanceArn,
                    "PermissionSetArn" => PermissionSetArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_accounts_for_provisioned_permission_set(instance_arn, permission_set_arn)
    list_accounts_for_provisioned_permission_set(instance_arn, permission_set_arn, params::Dict{String,<:Any})

Lists all the Amazon Web Services accounts where the specified permission set is
provisioned.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the PermissionSet from which the associated Amazon Web
  Services accounts will be listed.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to display for the PermissionSet.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
- `"ProvisioningStatus"`: The permission set provisioning status for an Amazon Web Services
  account.
"""
function list_accounts_for_provisioned_permission_set(
    InstanceArn, PermissionSetArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListAccountsForProvisionedPermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_accounts_for_provisioned_permission_set(
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListAccountsForProvisionedPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_instances()
    list_instances(params::Dict{String,<:Any})

Lists the SSO instances that the caller has access to.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to display for the instance.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_instances(; aws_config::AbstractAWSConfig=global_aws_config())
    return sso_admin(
        "ListInstances"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_instances(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListInstances", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    list_managed_policies_in_permission_set(instance_arn, permission_set_arn)
    list_managed_policies_in_permission_set(instance_arn, permission_set_arn, params::Dict{String,<:Any})

Lists the IAM managed policy that is attached to a specified permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the PermissionSet whose managed policies will be listed.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to display for the PermissionSet.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_managed_policies_in_permission_set(
    InstanceArn, PermissionSetArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListManagedPoliciesInPermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_managed_policies_in_permission_set(
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListManagedPoliciesInPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_permission_set_provisioning_status(instance_arn)
    list_permission_set_provisioning_status(instance_arn, params::Dict{String,<:Any})

Lists the status of the permission set provisioning requests for a specified SSO instance.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filter"`: Filters results based on the passed attribute value.
- `"MaxResults"`: The maximum number of results to display for the assignment.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_permission_set_provisioning_status(
    InstanceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListPermissionSetProvisioningStatus",
        Dict{String,Any}("InstanceArn" => InstanceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_permission_set_provisioning_status(
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListPermissionSetProvisioningStatus",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("InstanceArn" => InstanceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_permission_sets(instance_arn)
    list_permission_sets(instance_arn, params::Dict{String,<:Any})

Lists the PermissionSets in an SSO instance.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to display for the assignment.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_permission_sets(
    InstanceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListPermissionSets",
        Dict{String,Any}("InstanceArn" => InstanceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_permission_sets(
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListPermissionSets",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("InstanceArn" => InstanceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_permission_sets_provisioned_to_account(account_id, instance_arn)
    list_permission_sets_provisioned_to_account(account_id, instance_arn, params::Dict{String,<:Any})

Lists all the permission sets that are provisioned to a specified Amazon Web Services
account.

# Arguments
- `account_id`: The identifier of the Amazon Web Services account from which to list the
  assignments.
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to display for the assignment.
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
- `"ProvisioningStatus"`: The status object for the permission set provisioning operation.
"""
function list_permission_sets_provisioned_to_account(
    AccountId, InstanceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListPermissionSetsProvisionedToAccount",
        Dict{String,Any}("AccountId" => AccountId, "InstanceArn" => InstanceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_permission_sets_provisioned_to_account(
    AccountId,
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListPermissionSetsProvisionedToAccount",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("AccountId" => AccountId, "InstanceArn" => InstanceArn),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    list_tags_for_resource(instance_arn, resource_arn)
    list_tags_for_resource(instance_arn, resource_arn, params::Dict{String,<:Any})

Lists the tags that are attached to a specified resource.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `resource_arn`: The ARN of the resource with the tags to be listed.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"NextToken"`: The pagination token for the list API. Initially the value is null. Use
  the output of previous API calls to make subsequent calls.
"""
function list_tags_for_resource(
    InstanceArn, ResourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "ListTagsForResource",
        Dict{String,Any}("InstanceArn" => InstanceArn, "ResourceArn" => ResourceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    InstanceArn,
    ResourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ListTagsForResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "ResourceArn" => ResourceArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    provision_permission_set(instance_arn, permission_set_arn, target_type)
    provision_permission_set(instance_arn, permission_set_arn, target_type, params::Dict{String,<:Any})

The process by which a specified permission set is provisioned to the specified target.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set.
- `target_type`: The entity type for which the assignment will be created.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"TargetId"`: TargetID is an Amazon Web Services account identifier, typically a 10-12
  digit string (For example, 123456789012).
"""
function provision_permission_set(
    InstanceArn,
    PermissionSetArn,
    TargetType;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ProvisionPermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn,
            "PermissionSetArn" => PermissionSetArn,
            "TargetType" => TargetType,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function provision_permission_set(
    InstanceArn,
    PermissionSetArn,
    TargetType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "ProvisionPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "PermissionSetArn" => PermissionSetArn,
                    "TargetType" => TargetType,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    put_inline_policy_to_permission_set(inline_policy, instance_arn, permission_set_arn)
    put_inline_policy_to_permission_set(inline_policy, instance_arn, permission_set_arn, params::Dict{String,<:Any})

Attaches an IAM inline policy to a permission set.  If the permission set is already
referenced by one or more account assignments, you will need to call
ProvisionPermissionSet  after this action to apply the corresponding IAM policy updates to
all assigned accounts.

# Arguments
- `inline_policy`: The IAM inline policy to attach to a PermissionSet.
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set.

"""
function put_inline_policy_to_permission_set(
    InlinePolicy,
    InstanceArn,
    PermissionSetArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "PutInlinePolicyToPermissionSet",
        Dict{String,Any}(
            "InlinePolicy" => InlinePolicy,
            "InstanceArn" => InstanceArn,
            "PermissionSetArn" => PermissionSetArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function put_inline_policy_to_permission_set(
    InlinePolicy,
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "PutInlinePolicyToPermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InlinePolicy" => InlinePolicy,
                    "InstanceArn" => InstanceArn,
                    "PermissionSetArn" => PermissionSetArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(instance_arn, resource_arn, tags)
    tag_resource(instance_arn, resource_arn, tags, params::Dict{String,<:Any})

Associates a set of tags with a specified resource.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `resource_arn`: The ARN of the resource with the tags to be listed.
- `tags`: A set of key-value pairs that are used to manage the resource.

"""
function tag_resource(
    InstanceArn, ResourceArn, Tags; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "TagResource",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "ResourceArn" => ResourceArn, "Tags" => Tags
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    InstanceArn,
    ResourceArn,
    Tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "TagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "ResourceArn" => ResourceArn,
                    "Tags" => Tags,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(instance_arn, resource_arn, tag_keys)
    untag_resource(instance_arn, resource_arn, tag_keys, params::Dict{String,<:Any})

Disassociates a set of tags from a specified resource.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `resource_arn`: The ARN of the resource with the tags to be listed.
- `tag_keys`: The keys of tags that are attached to the resource.

"""
function untag_resource(
    InstanceArn, ResourceArn, TagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "UntagResource",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "ResourceArn" => ResourceArn, "TagKeys" => TagKeys
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    InstanceArn,
    ResourceArn,
    TagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "UntagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn,
                    "ResourceArn" => ResourceArn,
                    "TagKeys" => TagKeys,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_instance_access_control_attribute_configuration(instance_access_control_attribute_configuration, instance_arn)
    update_instance_access_control_attribute_configuration(instance_access_control_attribute_configuration, instance_arn, params::Dict{String,<:Any})

Updates the Amazon Web Services SSO identity store attributes that you can use with the
Amazon Web Services SSO instance for attributes-based access control (ABAC). When using an
external identity provider as an identity source, you can pass attributes through the SAML
assertion as an alternative to configuring attributes from the Amazon Web Services SSO
identity store. If a SAML assertion passes any of these attributes, Amazon Web Services SSO
replaces the attribute value with the value from the Amazon Web Services SSO identity
store. For more information about ABAC, see Attribute-Based Access Control in the Amazon
Web Services SSO User Guide.

# Arguments
- `instance_access_control_attribute_configuration`: Updates the attributes for your ABAC
  configuration.
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.

"""
function update_instance_access_control_attribute_configuration(
    InstanceAccessControlAttributeConfiguration,
    InstanceArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "UpdateInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}(
            "InstanceAccessControlAttributeConfiguration" =>
                InstanceAccessControlAttributeConfiguration,
            "InstanceArn" => InstanceArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_instance_access_control_attribute_configuration(
    InstanceAccessControlAttributeConfiguration,
    InstanceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "UpdateInstanceAccessControlAttributeConfiguration",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceAccessControlAttributeConfiguration" =>
                        InstanceAccessControlAttributeConfiguration,
                    "InstanceArn" => InstanceArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_permission_set(instance_arn, permission_set_arn)
    update_permission_set(instance_arn, permission_set_arn, params::Dict{String,<:Any})

Updates an existing permission set.

# Arguments
- `instance_arn`: The ARN of the SSO instance under which the operation will be executed.
  For more information about ARNs, see Amazon Resource Names (ARNs) and Amazon Web Services
  Service Namespaces in the Amazon Web Services General Reference.
- `permission_set_arn`: The ARN of the permission set.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: The description of the PermissionSet.
- `"RelayState"`: Used to redirect users within the application during the federation
  authentication process.
- `"SessionDuration"`: The length of time that the application user sessions are valid for
  in the ISO-8601 standard.
"""
function update_permission_set(
    InstanceArn, PermissionSetArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return sso_admin(
        "UpdatePermissionSet",
        Dict{String,Any}(
            "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_permission_set(
    InstanceArn,
    PermissionSetArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return sso_admin(
        "UpdatePermissionSet",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "InstanceArn" => InstanceArn, "PermissionSetArn" => PermissionSetArn
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
filename() = "day21.txt"

struct Food{T,S}
    ingredients::Set{T}
    allergens::Set{S}
end

function read_data()
    function parse_line(s)
        m = match(r"(.*) \(contains (.*)\)$", s)
        ingredients = split(m.captures[1], " ")
        allergens = split(m.captures[2], ", ")
        return Food(Set(ingredients), Set(allergens))
    end
    lines = readlines(filename())
    return parse_line.(lines)
end

function all_allergens(foods)
    return mapreduce(Base.Fix2(getproperty, :allergens),
        union, foods)
end

# Which ingredients might contain a specific allergen?
function candidate_ingredients(foods, allergen)
    related = [f for f in foods if allergen in f.allergens]
    return intersect([r.ingredients for r in related]...)
end

# Create a list of allergen => candidate ingredients
function create_work_list(foods)
    return Dict(a => candidate_ingredients(foods, a)
        for a in all_allergens(foods))
end

# Resovle the work list.
# If an allergen is mapped to exactly one ingredient, then
# it's resolved. Then, remove this ingredient from the work
# list. Repeat until all alergens are resolved.
function resolve(work_list)
    result = Dict()
    queue = collect(keys(work_list))
    while length(result) < length(work_list)
        allergen = popfirst!(queue)
        if length(work_list[allergen]) == 1
            ingredient = only(work_list[allergen])
            result[allergen] = ingredient
            for k in keys(work_list)  # remove from all others
                if k != allergen
                    delete!(work_list[k], ingredient)
                end
            end
        else
            push!(queue, allergen)
        end
    end
    return result
end

# Count how many ingredients are left after excluding the
# exclusion list.
function remaining_ingredients(foods, exclude_ingredients)
    cnt = 0
    for f in foods
        s = setdiff(f.ingredients, exclude_ingredients)
        cnt += length(s)
    end
    return cnt
end

function resolve_allergens(foods)
    work_list = create_work_list(foods)
    return resolve(work_list)
end

function part1()
    foods = read_data()
    mapped = resolve_allergens(foods)
    return remaining_ingredients(foods, collect(values(mapped)))
end

function part2()
    foods = read_data()
    mapped = resolve_allergens(foods)
    return join([mapped[k] for k in sort(collect(keys(mapped)))], ",")
end

ext: jl


text:
is_schedule_json_available() = isfile(joinpath(CACHE_DIR, "schedule.json"))

"""
Get the conference schedule as a nested JSON object.
On first call, the schedule is downloaded from Pretalx and cached for further usage.
"""
function get_conference_schedule()
    isassigned(jcon) || update_schedule()
    return jcon[]
end

"""
    update_schedule(; verbose=false, ignore_timeout=false)

Explicitly trigger a schedule update according to the specified CACHE_MODE.
"""
function update_schedule(; verbose=false, notimeout=false)
    local file
    to = TimerOutput()
    verbose && @info "Cache mode: $CACHE_MODE"
    usecache = CACHE_MODE != :NEVER
    download_dir = usecache ? CACHE_DIR : mktempdir()

    if CACHE_MODE != :ALWAYS
        verbose && @info "Downloading $(default_json_url()) to $download_dir"
        if usecache && !isdir(CACHE_DIR)
            verbose && @info "Cache directory $CACHE_DIR created."
            mkpath(CACHE_DIR)
        end

        timeout =
            (usecache && is_schedule_json_available()) ? (!notimeout ? TIMEOUT : Inf) : Inf
        verbose && @info "Timeout set to $timeout seconds."

        try
            @timeit to "download" file = download(
                default_json_url(), joinpath(download_dir, "schedule.json.tmp"); timeout
            )
            file = mv(
                joinpath(download_dir, "schedule.json.tmp"),
                joinpath(download_dir, "schedule.json");
                force=true,
            )
        catch err
            if usecache
                @warn "Download failed or timed out. Falling back to cached schedule (might be stale). " *
                      "You can try forcing matters with JuliaCon.update_schedule(notimeout=true) or " *
                      "skipping the update altogether via JuliaCon.set_cachemode(:ALWAYS)."
                file = joinpath(CACHE_DIR, "schedule.json")
            else
                error(
                    "Download failed. Not using the cache due to CACHE_MODE = $CACHE_MODE."
                )
            end
        end
    else
        verbose && @info "Loading cached schedule.json"
        is_schedule_json_available() || error(
            "Can't find cached schedule.json. Not downloading due to CACHE_MODE = $CACHE_MODE.",
        )
        file = joinpath(CACHE_DIR, "schedule.json")
    end

    @timeit to "parse2json" data = JSON.parsefile(file)
    @timeit to "json2struct" jcon[] = json2struct(data["schedule"]["conference"])

    verbose && @info string("Timings:\n", to)
    return nothing
end

"""
Given a track (i.e. a fixed day), it finds the talks that are running now (it only compares times).
"""
function _find_current_talk_in_track(track::JuliaConTrack; now=default_now())
    for talk in track.talks
        start_time = Time(talk.start) # time in UTC
        dur = Time(talk.duration)
        end_time = start_time + Hour(dur) + Minute(dur)
        if start_time <= Time(_datetime_to_utc(now)) < end_time
            return talk
        end
    end
    return nothing
end

"""
Given a fixed day, it finds the talks in all tracks that are running now (it only compares times).

Returns a vector of tuples of the type `(track::String, talk::JuliaConTalk)`.
"""
function _find_current_talks_on_day(
    d::JuliaConDay; now=default_now()
)::Vector{Tuple{String,JuliaConTalk}}
    query_result = Vector{Tuple{String,Union{Nothing,JuliaConTalk}}}(
        undef, length(d.tracks)
    )
    for (i, track) in enumerate(d.tracks)
        query_result[i] = (track.name, _find_current_talk_in_track(track; now=now))
    end
    return filter(x -> !isnothing(x[2]), query_result)
end

function get_running_talks(; now=default_now())
    jcon = get_conference_schedule()

    dayidx = findfirst(d -> d.date == Date(_datetime_to_utc(now)), jcon.days)
    if isnothing(dayidx)
        @info "There is no JuliaCon program today!"
        return nothing
    end

    d = jcon.days[dayidx]
    if !(d.start <= DateTime(_datetime_to_utc(now)) <= d.stop)
        @info "There is no JuliaCon program now!"
        return nothing
    end

    current_talks = _find_current_talks_on_day(d; now=now)
    return current_talks
end

function _track2color(track::String)
    if track == "Red"
        return :red
    elseif track == "Green"
        return :green
    elseif track == "Purple"
        return :magenta
    elseif track == "Blue"
        return :blue
    else
        return :default
    end
end

function _print_running_talks(current_talks; now=default_now())
    !isnothing(current_talks) || return nothing
    # println()
    # println(Dates.format(default_now(), "HH:MM dd-mm-YYYY"))
    for (track, talk) in current_talks
        println()
        printstyled(track; bold=true, color=_track2color(track))
        println()
        println("\t", talk.title, " (", string(talk.type), ")")
        println("\t", "├─ ", speakers2str(talk.speaker))
        println("\t", "└─ ", talk.url)
    end
    println("\n")
    println("(Full schedule: https://pretalx.com/juliacon2021/schedule)")
    return nothing
end

function now(::Val{:text}; now)
    current_talks = get_running_talks(; now=now)
    str = ""
    if !isnothing(current_talks)
        for (track, talk) in current_talks
            str *= """
            $track
            \t$(talk.title) ($(string(talk.type)))
            \t├─ $(JuliaCon.speakers2str(talk.speaker))
            \t└─ $(talk.url)
            """
        end
    end
    str *= "\n(Full schedule: https://pretalx.com/juliacon2021/schedule)"
    return str
end

function now(::Val{:terminal}; now)
    current_talks = get_running_talks(; now=now)
    _print_running_talks(current_talks; now=now)
    return nothing
end

# A dispatcher for the `now` methods. Default to terminal output.
now(; now=default_now(), output=:terminal) = JuliaCon.now(Val(output); now=now)

function get_today(; now=default_now())
    jcon = get_conference_schedule()

    dayidx = findfirst(d -> d.date == Date(_datetime_to_utc(now)), jcon.days)
    if isnothing(dayidx)
        @info "There is no JuliaCon program today!"
        return nothing
    end

    schedule = [(track.name, track.talks) for track in jcon.days[dayidx].tracks]
    return schedule
end

speakers2str(speaker::Vector{String}) = join(speaker, ", ")

_datetime_to_utc(t::ZonedDateTime) = astimezone(t, JULIACON_TIMEZONE)
_datetime_to_utc(t) = ZonedDateTime(t, JULIACON_TIMEZONE)

function _get_current_talk_highlighter(talks; now=default_now())
    for (i, talk) in enumerate(talks)
        start_time = Time(talk.start)
        dur = Time(talk.duration)
        end_time = start_time + Hour(dur) + Minute(dur)
        if start_time <= Time(_datetime_to_utc(now)) < end_time
            return Highlighter((data, m, n) -> m == i, crayon"yellow")
        end
    end
    return Highlighter((data, m, n) -> false, crayon"yellow")
end

function _get_today_tables(;
    now=default_now(), track=nothing, terminal_links=TERMINAL_LINKS
)
    track_schedules = get_today(; now=now)
    isnothing(track_schedules) && return (nothing, nothing, nothing)

    tracks = String[]
    tables = Matrix{Union{String,URLTextCell}}[]
    highlighters = Union{Nothing,Highlighter}[]
    for (tr, talks) in track_schedules
        !isnothing(track) && tr != track && continue
        push!(tracks, tr)

        data = Matrix{Union{String,URLTextCell}}(undef, length(talks), 4)
        for (i, talk) in enumerate(talks)
            data[i, 1] = Dates.format(_jcontime_to_localtime(Time(talk.start)), "HH:MM")
            data[i, 2] = terminal_links ? URLTextCell(talk.title, talk.url) : talk.title
            data[i, 3] = JuliaCon.abbrev(talk.type)
            data[i, 4] = JuliaCon.speakers2str(talk.speaker)
        end
        push!(tables, data)

        h_current = _get_current_talk_highlighter(talks; now=now)
        push!(highlighters, h_current)
    end

    @assert length(tables) == length(highlighters) == length(tracks)
    return (tracks, tables, highlighters)
end

function _jcontime_to_localtime(t)
    jcon_datetime = ZonedDateTime(
        DateTime(TimeZones.today(JULIACON_TIMEZONE), t), JULIACON_TIMEZONE
    )
    local_datetime = astimezone(jcon_datetime, localzone())
    return Time(local_datetime)
end

# A dispatcher for the `today` methods. Defaults to terminal output.
function today(;
    now=default_now(),
    track=nothing,
    terminal_links=TERMINAL_LINKS,
    output=:terminal, # can take the :text value to output a Vector{String}
)
    return today(Val(output); now, track, terminal_links)
end

function today(::Val{:terminal}; now, track, terminal_links)
    tracks, tables, highlighters = _get_today_tables(; now, track, terminal_links)
    isnothing(tables) && return nothing

    header = (["Time", "Title", "Type", "Speaker"],)
    header_crayon = crayon"dark_gray bold"
    border_crayon = crayon"dark_gray"
    h_times = Highlighter((data, i, j) -> j == 1, crayon"white bold")

    for j in eachindex(tracks)
        track = tracks[j]
        data = tables[j]
        h_current = highlighters[j]
        println()
        pretty_table(
            data;
            title=track,
            title_crayon=Crayon(; foreground=_track2color(track), bold=true),
            header=header,
            header_crayon=header_crayon,
            border_crayon=border_crayon,
            highlighters=(h_times, h_current),
            tf=tf_unicode_rounded,
            alignment=[:c, :l, :c, :l],
        )
    end

    println()
    printstyled("Currently running talks are highlighted in ")
    printstyled("yellow"; color=:yellow)
    printstyled(".")
    println()
    println()
    print(abbrev(Talk), " = Talk, ")
    print(abbrev(LightningTalk), " = Lightning Talk, ")
    print(abbrev(SponsorTalk), " = Sponsor Talk, ")
    println(abbrev(Keynote), " = Keynote, ")
    print(abbrev(Workshop), " = Workshop, ")
    print(abbrev(Minisymposium), " = Minisymposium, ")
    println(abbrev(BoF), " = Birds of Feather, ")
    print(abbrev(Experience), " = Experience, ")
    println(abbrev(VirtualPoster), " = Virtual Poster")
    println()
    println("Check out https://pretalx.com/juliacon2021/schedule for more information.")
    return nothing
end

function today(::Val{:text}; now, track, terminal_links)
    tracks, tables, highlighters = _get_today_tables(; now, track, terminal_links)
    isnothing(tables) && return nothing

    header = (["Time", "Title", "Type", "Speaker"],)
    header_crayon = crayon"dark_gray bold"
    border_crayon = crayon"dark_gray"
    h_times = Highlighter((data, i, j) -> j == 1, crayon"white bold")

    strings = Vector{String}()
    for j in eachindex(tracks)
        track = tracks[j]
        data = tables[j]
        h_current = highlighters[j]
        str = pretty_table(
            String,
            data;
            title=track,
            title_crayon=Crayon(; foreground=_track2color(track), bold=true),
            header=header,
            header_crayon=header_crayon,
            border_crayon=border_crayon,
            highlighters=(h_times, h_current),
            tf=tf_unicode_rounded,
            alignment=[:c, :l, :c, :l],
        )
        push!(strings, str)
    end

    legend = """
    Currently running talks are highlighted in yellow (or not cause WIP).

    $(JuliaCon.abbrev(JuliaCon.Talk)) = Talk, $(JuliaCon.abbrev(JuliaCon.LightningTalk)) = Lightning Talk, $(JuliaCon.abbrev(JuliaCon.SponsorTalk)) = Sponsor Talk, $(JuliaCon.abbrev(JuliaCon.Keynote)) = Keynote,
    $(JuliaCon.abbrev(JuliaCon.Workshop)) = Workshop, $(JuliaCon.abbrev(JuliaCon.Minisymposium)) = Minisymposium, $(JuliaCon.abbrev(JuliaCon.BoF)) = Birds of Feather,
    $(JuliaCon.abbrev(JuliaCon.Experience)) = Experience, $(JuliaCon.abbrev(JuliaCon.VirtualPoster)) = Virtual Poster

    Check out https://pretalx.com/juliacon2021/schedule for more information.
    """
    push!(strings, legend)
    return strings
end


text:
T=0
try
    h=dlopen(:libdfdct_wrapping)
    global T=3
    dlclose(h)
catch
    @warn "Skipping joCurvelet2D tests - libdfdct_wrapping not found"
end

tsname="joCurvelet2D"
@testset "$tsname" begin
for t=1:T # start test loop
    m=32*t
    Awr=joCurvelet2D(m,m)
    Awc=joCurvelet2D(m,m;DDT=ComplexF64,real_crvlts=false)
    Acr=joCurvelet2D(m,m;all_crvlts=true)
    Acc=joCurvelet2D(m,m;DDT=ComplexF64,all_crvlts=true,real_crvlts=false)

    verbose && println("$tsname ($m,$m)")
    @testset "$m x $m" begin
        @test isadjoint(Awr)[1]
        @test isadjoint(Awc)[1]
        @test isadjoint(Acr)[1]
        @test isadjoint(Acc)[1]
        @test islinear(Awr)[1]
        @test islinear(Awc)[1]
        @test islinear(Acr)[1]
        @test islinear(Acc)[1]
    end

end # end test loop
end


text:
using CPLEX

include(joinpath(Pkg.dir("MathProgBase"),"test","linprog.jl"))
linprogtest(CplexSolver(CPX_PARAM_PREIND=0, CPX_PARAM_LPMETHOD=2))

include(joinpath(Pkg.dir("MathProgBase"),"test","mixintprog.jl"))
mixintprogtest(CplexSolver())

include(joinpath(Pkg.dir("MathProgBase"),"test","quadprog.jl"))
quadprogtest(CplexSolver())
socptest(CplexSolver())

include(joinpath(Pkg.dir("MathProgBase"),"test","linproginterface.jl"))
linprogsolvertest(CplexSolver())

include(joinpath(Pkg.dir("MathProgBase"),"test","conicinterface.jl"))
coniclineartest(CplexSolver())
conicSOCtest(CplexSolver())
conicSOCRotatedtest(CplexSolver())
conicSOCINTtest(CplexSolver())


text:
using Pkg; for p in ("ZipFile","JLD2","FileIO"); haskey(Pkg.installed(),p) || Pkg.add(p); end
using ZipFile, FileIO

# nltkurl has subdirectories like corpora, taggers, stemmers etc.
nltkurl = "https://raw.githubusercontent.com/nltk/nltk_data/gh-pages/packages"
nltkdir = joinpath(@__DIR__, "nltk")

"""
    brown()

Return (data, words, tags) where data is an array of (x,y) pairs, each pair represents a
sentence, x is an UInt16 array of word ids, y is an UInt16 array of postag ids. words and
tags are String arrays to convert word and tag ids to strings. Ids are assigned in order of
frequency, i.e. words[1] is the most frequent word.
"""
function brown()
    ispath(nltkdir) || mkpath(nltkdir)
    jldfile = joinpath(nltkdir,"brown.jld2")
    if !isfile(jldfile)
        file = joinpath(nltkdir,"brown.zip")
        isfile(file) || download("$nltkurl/corpora/brown.zip", file)
        r = ZipFile.Reader(file)
        data = []  # an array of (x,y) pairs where x is a word sequence, y is a tag sequence
        wdict = Dict{String,Int}()
        tdict = Dict{String,Int}()
        for f in r.files
            occursin(r"^brown/c.\d\d$", f.name) || continue
            for l in eachline(f)
                x = []; y = []
                for s in split(l)
                    t = findlast(isequal('/'), s)
                    word,tag = s[1:t-1],s[t+1:end]
                    wdict[word] = 1 + get(wdict,word,0)
                    tdict[tag] = 1 + get(tdict,tag,0)
                    push!(x, word)
                    push!(y, tag)
                end
                isempty(x) || push!(data, (x,y))
            end
        end
        close(r)
        # Assign ids based on frequency
        words = Array{String}(undef, length(wdict)); tags = Array{String}(undef, length(tdict))
        n = 1; for (c,w) in sort(collect(zip(values(wdict),keys(wdict))), rev=true); wdict[w] = n; words[n] = w; n+=1; end
        n = 1; for (c,t) in sort(collect(zip(values(tdict),keys(tdict))), rev=true); tdict[t] = n; tags[n] = t; n+=1; end
        data = map(data) do xy; (UInt16[ wdict[x] for x in xy[1] ], UInt16[ tdict[y] for y in xy[2] ]); end
        save(jldfile, "data", data, "words", words, "tags", tags)
    end
    load(jldfile, "data", "words", "tags")
end


text:
#=
Copyright (c) 2015, Intel Corporation
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
=#

import CompilerTools.AstWalker
export constant_fold

binops = Set([:+; :-; :*; :/])

function constant_folder(node, symbol_table, top_level_number, is_top_level, read)
  if isa(node, Expr)
    if node.head == :(=)
      rhs = AstWalker.AstWalk(node.args[2], constant_folder, symbol_table)
      if isa(rhs, Number)
        symbol_table[node.args[1]] = rhs
      end
      return node
    elseif node.head == :call
      if in(node.args[1], binops) && length(node.args)==3
	      node.args[2] = AstWalker.AstWalk(node.args[2], constant_folder, symbol_table)[1]
	      node.args[3] = AstWalker.AstWalk(node.args[3], constant_folder, symbol_table)[1]
        if isa(node.args[2], Number) && isa(node.args[3], Number)
          return eval(node)
        end
      end
    end
  elseif isa(node, Symbol)
    if haskey(symbol_table, node)
      return symbol_table[node]
    end
  elseif isa(node, Number)
    return node
  end
  return CompilerTools.AstWalker.ASTWALK_RECURSE
end

function constant_fold(fn)
	symbol_table = Dict{Symbol, Number}()
	fn = AstWalker.AstWalk(fn, constant_folder, symbol_table)
	return fn
end

#=
macro constant_fold(fn)
	symbol_table = Dict{Symbol, Number}()
	AstWalker.AstWalk(fn, constant_folder, symbol_table)
  println(symbol_table)
  println(fn)
  return esc(fn)
end

@constant_fold function test(z)
  a = 3
  b = 4
  c = a - b
  d = z + c
  return d
end
=#