aws

package
v0.9.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 1, 2018 License: Apache-2.0 Imports: 30 Imported by: 0

Documentation

Index

Constants

View Source
const AmazonAccountId = "amazon"
View Source
const CanonicalAccountId = "099720109477"
View Source
const CentOsAccountId = "679593333241"

Variables

This section is empty.

Functions

func AssertS3BucketExists

func AssertS3BucketExists(t *testing.T, region string, name string)

Check if the given S3 bucket exists in the given region and fail the test if it does not

func AssertS3BucketExistsE

func AssertS3BucketExistsE(t *testing.T, region string, name string) error

Check if the given S3 bucket exists in the given region and return an error if it does not

func AssumeRole added in v0.9.3

func AssumeRole(sess *session.Session, roleARN string) *session.Session

AssumeRole mutates the provided session by obtaining new credentials by assuming the role provided in roleARN.

func CreateAwsCredentials

func CreateAwsCredentials(accessKeyId string, secretAccessKey string) *credentials.Credentials

Create an AWS Credentials configuration with specific AWS credentials.

func CreateAwsCredentialsWithSessionToken

func CreateAwsCredentialsWithSessionToken(accessKeyId, secretAccessKey, sessionToken string) *credentials.Credentials

Create an AWS Credentials configuration with temporary AWS credentials by including a session token (used for authenticating with MFA)

func CreateAwsSessionFromRole added in v0.9.3

func CreateAwsSessionFromRole(region string, roleARN string) (*session.Session, error)

CreateAwsSessionFromRole returns a new AWS session after assuming the role whose ARN is provided in roleARN.

func CreateAwsSessionWithCreds

func CreateAwsSessionWithCreds(region string, accessKeyId string, secretAccessKey string) (*session.Session, error)

Create a new AWS session using explicit credentials. This is useful if you want to create an IAM User dynamically and create an AWS session authenticated as the new IAM User.

func CreateAwsSessionWithMfa

func CreateAwsSessionWithMfa(region string, stsClient *sts.STS, mfaDevice *iam.VirtualMFADevice) (*session.Session, error)

Create a new AWS session authenticated using an MFA token retrieved using the given STS client and MFA Device

func CreateMfaDevice

func CreateMfaDevice(t *testing.T, iamClient *iam.IAM, deviceName string) *iam.VirtualMFADevice

Create an MFA device using the given IAM client

func CreateMfaDeviceE

func CreateMfaDeviceE(t *testing.T, iamClient *iam.IAM, deviceName string) (*iam.VirtualMFADevice, error)

Create an MFA device using the given IAM client

func CreateRandomQueue

func CreateRandomQueue(t *testing.T, awsRegion string, prefix string) string

Create a new SQS queue with a random name that starts with the given prefix and return the queue URL

func CreateRandomQueueE

func CreateRandomQueueE(t *testing.T, awsRegion string, prefix string) (string, error)

Create a new SQS queue with a random name that starts with the given prefix and return the queue URL

func CreateS3Bucket

func CreateS3Bucket(t *testing.T, region string, name string)

Create an S3 bucket in the given region with the given name. Note that S3 bucket names must be globally unique.

func CreateS3BucketE

func CreateS3BucketE(t *testing.T, region string, name string) error

Create an S3 bucket in the given region with the given name. Note that S3 bucket names must be globally unique.

func CreateSnsTopic

func CreateSnsTopic(t *testing.T, region string, snsTopicName string) string

Create an SNS Topic and return the ARN

func CreateSnsTopicE

func CreateSnsTopicE(t *testing.T, region string, snsTopicName string) (string, error)

Create an SNS Topic and return the ARN

func DeleteAmi

func DeleteAmi(t *testing.T, region string, imageId string)

Delete the given AMI in the given region

func DeleteAmiE

func DeleteAmiE(t *testing.T, region string, imageId string) error

Delete the given AMI in the given region

func DeleteEC2KeyPair

func DeleteEC2KeyPair(t *testing.T, keyPair *Ec2Keypair)

Delete an EC2 Keypair

func DeleteEC2KeyPairE

func DeleteEC2KeyPairE(t *testing.T, keyPair *Ec2Keypair) error

Delete an EC2 Keypair

func DeleteMessageFromQueue

func DeleteMessageFromQueue(t *testing.T, awsRegion string, queueUrl string, receipt string)

Delete the message with the given receipt from the SQS queue with the given URL

func DeleteMessageFromQueueE

func DeleteMessageFromQueueE(t *testing.T, awsRegion string, queueUrl string, receipt string) error

Delete the message with the given receipt from the SQS queue with the given URL

func DeleteQueue

func DeleteQueue(t *testing.T, awsRegion string, queueUrl string)

Delete the SQS queue with the given URL

func DeleteQueueE

func DeleteQueueE(t *testing.T, awsRegion string, queueUrl string) error

Delete the SQS queue with the given URL

func DeleteS3Bucket

func DeleteS3Bucket(t *testing.T, region string, name string)

Destroy the S3 bucket in the given region with the given name.

func DeleteS3BucketE

func DeleteS3BucketE(t *testing.T, region string, name string) error

Destroy the S3 bucket in the given region with the given name.

func DeleteSNSTopic

func DeleteSNSTopic(t *testing.T, region string, snsTopicArn string)

Delete an SNS Topic

func DeleteSNSTopicE

func DeleteSNSTopicE(t *testing.T, region string, snsTopicArn string) error

Delete an SNS Topic

func EnableMfaDevice

func EnableMfaDevice(t *testing.T, iamClient *iam.IAM, mfaDevice *iam.VirtualMFADevice)

Enable a newly created MFA Device by supplying the first two one-time passwords, so that it can be used for future logins by the given IAM User

func EnableMfaDeviceE

func EnableMfaDeviceE(t *testing.T, iamClient *iam.IAM, mfaDevice *iam.VirtualMFADevice) error

Enable a newly created MFA Device by supplying the first two one-time passwords, so that it can be used for future logins by the given IAM User

func FindS3BucketWithTag

func FindS3BucketWithTag(t *testing.T, awsRegion string, key string, value string) string

Find the name of the S3 bucket in the given region with the given tag key=value

func FindS3BucketWithTagE

func FindS3BucketWithTagE(t *testing.T, awsRegion string, key string, value string) (string, error)

Find the name of the S3 bucket in the given region with the given tag key=value

func FindVpcName

func FindVpcName(vpc *ec2.Vpc) string

Extract the VPC name from its tags (if any). Fall back to "Default" if it's the default VPC or empty string otherwise.

func GetAccountId

func GetAccountId(t *testing.T) string

Get the Account ID for the currently logged in IAM User.

func GetAccountIdE

func GetAccountIdE(t *testing.T) (string, error)

Get the Account ID for the currently logged in IAM User.

func GetAcmCertificateArn

func GetAcmCertificateArn(t *testing.T, awsRegion string, certDomainName string) string

Get the ACM certificate for the given domain name in the given region

func GetAcmCertificateArnE added in v0.9.0

func GetAcmCertificateArnE(t *testing.T, awsRegion string, certDomainName string) (string, error)

Get the ACM certificate for the given domain name in the given region

func GetAllAwsRegions

func GetAllAwsRegions(t *testing.T) []string

Get the list of AWS regions available in this account

func GetAllAwsRegionsE

func GetAllAwsRegionsE(t *testing.T) ([]string, error)

Get the list of AWS regions available in this account

func GetAmazonLinuxAmi

func GetAmazonLinuxAmi(t *testing.T, region string) string

Return an Amazon Linux AMI HVM, SSD Volume Type public AMI for the given region.

func GetAmazonLinuxAmiE

func GetAmazonLinuxAmiE(t *testing.T, region string) (string, error)

Return an Amazon Linux AMI HVM, SSD Volume Type public AMI for the given region.

func GetAvailabilityZones

func GetAvailabilityZones(t *testing.T, region string) []string

Get the Availability Zones for a given AWS region. Note that for certain regions (e.g. us-east-1), different AWS accounts have access to different availability zones.

func GetAvailabilityZonesE

func GetAvailabilityZonesE(t *testing.T, region string) ([]string, error)

Get the Availability Zones for a given AWS region. Note that for certain regions (e.g. us-east-1), different AWS accounts have access to different availability zones.

func GetCentos7Ami

func GetCentos7Ami(t *testing.T, region string) string

Return a CentOS 7 public AMI from the given region. WARNING: you may have to accept the terms & conditions of this AMI in AWS MarketPlace for your AWS Account before you can successfully launch the AMI.

func GetCentos7AmiE

func GetCentos7AmiE(t *testing.T, region string) (string, error)

Return a CentOS 7 public AMI from the given region. WARNING: you may have to accept the terms & conditions of this AMI in AWS MarketPlace for your AWS Account before you can successfully launch the AMI.

func GetCloudWatchLogEntries

func GetCloudWatchLogEntries(t *testing.T, awsRegion string, logStreamName string, logGroupName string) []string

Return the CloudWatch log messages in the given region for the given log stream and log group

func GetCloudWatchLogEntriesE

func GetCloudWatchLogEntriesE(t *testing.T, awsRegion string, logStreamName string, logGroupName string) ([]string, error)

Return the CloudWatch log messages in the given region for the given log stream and log group

func GetCmkArn

func GetCmkArn(t *testing.T, region string, cmkId string) string

Get the ARN of a KMS Customer Master Key (CMK) in the given region with the given ID. The ID can be an alias, such as "alias/my-cmk".

func GetCmkArnE

func GetCmkArnE(t *testing.T, region string, cmkId string) (string, error)

Get the ARN of a KMS Customer Master Key (CMK) in the given region with the given ID. The ID can be an alias, such as "alias/my-cmk".

func GetEc2InstanceIdsByTag

func GetEc2InstanceIdsByTag(t *testing.T, region string, tagName string, tagValue string) []string

Return all the IDs of EC2 instances in the given region with the given tag

func GetEc2InstanceIdsByTagE

func GetEc2InstanceIdsByTagE(t *testing.T, region string, tagName string, tagValue string) ([]string, error)

Return all the IDs of EC2 instances in the given region with the given tag

func GetEcsOptimizedAmazonLinuxAmi

func GetEcsOptimizedAmazonLinuxAmi(t *testing.T, region string) string

Return an Amazon ECS-Optimized Amazon Linux AMI for the given region. This AMI is useful for running an ECS cluster.

func GetEcsOptimizedAmazonLinuxAmiE

func GetEcsOptimizedAmazonLinuxAmiE(t *testing.T, region string) (string, error)

Return an Amazon ECS-Optimized Amazon Linux AMI for the given region. This AMI is useful for running an ECS cluster.

func GetFirstTwoOctets

func GetFirstTwoOctets(cidrBlock string) string

func GetIamCurrentUserArn

func GetIamCurrentUserArn(t *testing.T) string

Get the ARN for the current IAM user

func GetIamCurrentUserArnE

func GetIamCurrentUserArnE(t *testing.T) (string, error)

Get the ARN for the current IAM user

func GetIamCurrentUserName

func GetIamCurrentUserName(t *testing.T) string

Get the username fo the current IAM user

func GetIamCurrentUserNameE

func GetIamCurrentUserNameE(t *testing.T) (string, error)

Get the username fo the current IAM user

func GetInstanceIdsForAsg added in v0.9.0

func GetInstanceIdsForAsg(t *testing.T, asgName string, awsRegion string) []string

Get the IDs of EC2 Instances in the given ASG

func GetInstanceIdsForAsgE added in v0.9.0

func GetInstanceIdsForAsgE(t *testing.T, asgName string, awsRegion string) ([]string, error)

Get the IDs of EC2 Instances in the given ASG

func GetMostRecentAmiId

func GetMostRecentAmiId(t *testing.T, region string, ownerId string, filters map[string][]string) string

Get the ID of the most recent AMI in the given region that has the given owner and matches the given filters. Each filter should correspond to the name and values of a filter supported by DescribeImagesInput: https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#DescribeImagesInput

func GetMostRecentAmiIdE

func GetMostRecentAmiIdE(t *testing.T, region string, ownerId string, filters map[string][]string) (string, error)

Get the ID of the most recent AMI in the given region that has the given owner and matches the given filters. Each filter should correspond to the name and values of a filter supported by DescribeImagesInput: https://docs.aws.amazon.com/sdk-for-go/api/service/ec2/#DescribeImagesInput

func GetPublicIpOfEc2Instance added in v0.9.0

func GetPublicIpOfEc2Instance(t *testing.T, instanceId string, awsRegion string) string

Get the public IP address of the given EC2 Instance in the given region

func GetPublicIpOfEc2InstanceE added in v0.9.0

func GetPublicIpOfEc2InstanceE(t *testing.T, instanceId string, awsRegion string) (string, error)

Get the public IP address of the given EC2 Instance in the given region

func GetPublicIpsOfEc2Instances added in v0.9.1

func GetPublicIpsOfEc2Instances(t *testing.T, instanceIds []string, awsRegion string) map[string]string

Get the public IP address of the given EC2 Instance in the given region. Returns a map of instance ID to IP address.

func GetPublicIpsOfEc2InstancesE added in v0.9.1

func GetPublicIpsOfEc2InstancesE(t *testing.T, instanceIds []string, awsRegion string) (map[string]string, error)

Get the public IP address of the given EC2 Instance in the given region. Returns a map of instance ID to IP address.

func GetRandomPrivateCidrBlock

func GetRandomPrivateCidrBlock(routingPrefix int) string

Get a random CIDR block from the range of acceptable private IP addresses per RFC 1918 (https://tools.ietf.org/html/rfc1918#section-3) The routingPrefix refers to the "/28" in 1.2.3.4/28. Note that, as written, this function will return a subset of all valid ranges. Since we will probably use this function mostly for generating random CIDR ranges for VPCs and Subnets, having comprehensive set coverage is not essential.

func GetRandomRegion

func GetRandomRegion(t *testing.T, approvedRegions []string, forbiddenRegions []string) string

Get a randomly chosen AWS region. If approvedRegions is not empty, this will be a region from the approvedRegions list; otherwise, this method will fetch the latest list of regions from the AWS APIs and pick one of those. If forbiddenRegions is not empty, this method will make sure the returned region is not in the forbiddenRegions list.

func GetRandomRegionE

func GetRandomRegionE(t *testing.T, approvedRegions []string, forbiddenRegions []string) (string, error)

Get a randomly chosen AWS region. If approvedRegions is not empty, this will be a region from the approvedRegions list; otherwise, this method will fetch the latest list of regions from the AWS APIs and pick one of those. If forbiddenRegions is not empty, this method will make sure the returned region is not in the forbiddenRegions list.

func GetS3ObjectContents

func GetS3ObjectContents(t *testing.T, awsRegion string, bucket string, key string) string

Fetch the contents of the object in the given bucket with the given key and return it as a string

func GetS3ObjectContentsE

func GetS3ObjectContentsE(t *testing.T, awsRegion string, bucket string, key string) (string, error)

Fetch the contents of the object in the given bucket with the given key and return it as a string

func GetSyslogForInstance

func GetSyslogForInstance(t *testing.T, instanceId string, awsRegion string) string

Get the syslog for the Instance with the given ID in the given region. This should be available ~1 minute after an Instance boots and is very useful for debugging boot-time issues, such as an error in User Data.

func GetSyslogForInstanceE

func GetSyslogForInstanceE(t *testing.T, instanceId string, region string) (string, error)

Get the syslog for the Instance with the given ID in the given region. This should be available ~1 minute after an Instance boots and is very useful for debugging boot-time issues, such as an error in User Data.

func GetSyslogForInstancesInAsg

func GetSyslogForInstancesInAsg(t *testing.T, asgName string, awsRegion string) map[string]string

Get the syslog for each of the Instances in the given ASG in the given region. These logs should be available ~1 minute after the Instance boots and are very useful for debugging boot-time issues, such as an error in User Data. Returns a map of Instance Id -> Syslog for that Instance.

func GetSyslogForInstancesInAsgE

func GetSyslogForInstancesInAsgE(t *testing.T, asgName string, awsRegion string) (map[string]string, error)

Get the syslog for each of the Instances in the given ASG in the given region. These logs should be available ~1 minute after the Instance boots and are very useful for debugging boot-time issues, such as an error in User Data. Returns a map of Instance Id -> Syslog for that Instance.

func GetTagsForEc2Instance

func GetTagsForEc2Instance(t *testing.T, region string, instanceId string) map[string]string

Return all the tags for the given EC2 Instance

func GetTagsForEc2InstanceE

func GetTagsForEc2InstanceE(t *testing.T, region string, instanceId string) (map[string]string, error)

Return all the tags for the given EC2 Instance

func GetTimeBasedOneTimePassword

func GetTimeBasedOneTimePassword(mfaDevice *iam.VirtualMFADevice) (string, error)

Get a One-Time Password from the given mfaDevice. Per the RFC 6238 standard, this value will be different every 30 seconds.

func GetUbuntu1404Ami

func GetUbuntu1404Ami(t *testing.T, region string) string

Get the ID of the most recent Ubuntu 14.04 HVM x86_64 EBS GP2 AMI in the given region

func GetUbuntu1404AmiE

func GetUbuntu1404AmiE(t *testing.T, region string) (string, error)

Get the ID of the most recent Ubuntu 14.04 HVM x86_64 EBS GP2 AMI in the given region

func GetUbuntu1604Ami

func GetUbuntu1604Ami(t *testing.T, region string) string

Get the ID of the most recent Ubuntu 16.04 HVM x86_64 EBS GP2 AMI in the given region

func GetUbuntu1604AmiE

func GetUbuntu1604AmiE(t *testing.T, region string) (string, error)

Get the ID of the most recent Ubuntu 16.04 HVM x86_64 EBS GP2 AMI in the given region

func NewAcmClient

func NewAcmClient(t *testing.T, region string) *acm.ACM

Create a new ACM client

func NewAcmClientE added in v0.9.0

func NewAcmClientE(t *testing.T, awsRegion string) (*acm.ACM, error)

Create a new ACM client

func NewAsgClient added in v0.9.0

func NewAsgClient(t *testing.T, region string) *autoscaling.AutoScaling

Create an Auto Scaling Group client

func NewAsgClientE added in v0.9.0

func NewAsgClientE(t *testing.T, region string) (*autoscaling.AutoScaling, error)

Create an Auto Scaling Group client

func NewAuthenticatedSession

func NewAuthenticatedSession(region string) (*session.Session, error)

Get an AWS Session, checking that the user has credentials properly configured in their environment

func NewAuthenticatedSessionFromRole added in v0.9.3

func NewAuthenticatedSessionFromRole(region string, roleARN string) (*session.Session, error)

NewAuthenticatedSessionFromRole returns a new AWS Session after assuming the role whose ARN is provided in roleARN. If the credentials are not properly configured in the underlying environment, an error is returned.

func NewCloudWatchLogsClient

func NewCloudWatchLogsClient(t *testing.T, region string) *cloudwatchlogs.CloudWatchLogs

Create a new CloudWatch Logs client

func NewCloudWatchLogsClientE added in v0.9.0

func NewCloudWatchLogsClientE(t *testing.T, region string) (*cloudwatchlogs.CloudWatchLogs, error)

Create a new CloudWatch Logs client

func NewEc2Client

func NewEc2Client(t *testing.T, region string) *ec2.EC2

Create an EC2 client

func NewEc2ClientE added in v0.9.0

func NewEc2ClientE(t *testing.T, region string) (*ec2.EC2, error)

Create an EC2 client

func NewIamClient

func NewIamClient(t *testing.T, region string) *iam.IAM

Create a new IAM client

func NewIamClientE added in v0.9.0

func NewIamClientE(t *testing.T, region string) (*iam.IAM, error)

Create a new IAM client

func NewKmsClient

func NewKmsClient(t *testing.T, region string) *kms.KMS

Create a KMS client

func NewKmsClientE added in v0.9.0

func NewKmsClientE(t *testing.T, region string) (*kms.KMS, error)

Create a KMS client

func NewS3Client

func NewS3Client(t *testing.T, region string) *s3.S3

Create an S3 client

func NewS3ClientE added in v0.9.0

func NewS3ClientE(t *testing.T, region string) (*s3.S3, error)

Create an S3 client

func NewSnsClient

func NewSnsClient(t *testing.T, region string) *sns.SNS

Create a new SNS client

func NewSnsClientE added in v0.9.0

func NewSnsClientE(t *testing.T, region string) (*sns.SNS, error)

Create a new SNS client

func NewSqsClient

func NewSqsClient(t *testing.T, region string) *sqs.SQS

Create a new SQS client

func NewSqsClientE added in v0.9.0

func NewSqsClientE(t *testing.T, region string) (*sqs.SQS, error)

Create a new SQS client

func ReadPasswordPolicyMinPasswordLength

func ReadPasswordPolicyMinPasswordLength(iamClient *iam.IAM) (int, error)

func SendMessageToQueue

func SendMessageToQueue(t *testing.T, awsRegion string, queueUrl string, message string)

Send the given message to the SQS queue with the given URL

func SendMessageToQueueE

func SendMessageToQueueE(t *testing.T, awsRegion string, queueUrl string, message string) error

Send the given message to the SQS queue with the given URL

func TerminateInstance

func TerminateInstance(t *testing.T, region string, instanceId string)

Terminate the EC2 instance with the given ID in the given region

func TerminateInstanceE

func TerminateInstanceE(t *testing.T, region string, instanceId string) error

Terminate the EC2 instance with the given ID in the given region

Types

type CredentialsError

type CredentialsError struct {
	UnderlyingErr error
}

func (CredentialsError) Error

func (err CredentialsError) Error() string

type Ec2Keypair

type Ec2Keypair struct {
	*ssh.KeyPair
	Name   string // The name assigned in AWS to the EC2 Key Pair
	Region string // The AWS region where the EC2 Key Pair lives
}

func CreateAndImportEC2KeyPair

func CreateAndImportEC2KeyPair(t *testing.T, region string, name string) *Ec2Keypair

Generate a public/private KeyPair and import it into EC2 in the given region under the given name.

func CreateAndImportEC2KeyPairE

func CreateAndImportEC2KeyPairE(t *testing.T, region string, name string) (*Ec2Keypair, error)

Generate a public/private KeyPair and import it into EC2 in the given region under the given name.

func ImportEC2KeyPair

func ImportEC2KeyPair(t *testing.T, region string, name string, keyPair *ssh.KeyPair) *Ec2Keypair

Create a Key Pair in EC2 by importing an existing public key

func ImportEC2KeyPairE

func ImportEC2KeyPairE(t *testing.T, region string, name string, keyPair *ssh.KeyPair) (*Ec2Keypair, error)

Create a Key Pair in EC2 by importing an existing public key

type IpForEc2InstanceNotFound added in v0.9.0

type IpForEc2InstanceNotFound struct {
	InstanceId string
	AwsRegion  string
}

func (IpForEc2InstanceNotFound) Error added in v0.9.0

func (err IpForEc2InstanceNotFound) Error() string

type NoImagesFound

type NoImagesFound struct {
	Region  string
	OwnerId string
	Filters map[string][]string
}

func (NoImagesFound) Error

func (err NoImagesFound) Error() string

type QueueMessageResponse

type QueueMessageResponse struct {
	ReceiptHandle string
	MessageBody   string
	Error         error
}

func WaitForQueueMessage

func WaitForQueueMessage(t *testing.T, awsRegion string, queueUrl string, timeout int) QueueMessageResponse

Waits to receive a message from on the queueUrl. Since the API only allows us to wait a max 20 seconds for a new message to arrive, we must loop TIMEOUT/20 number of times to be able to wait for a total of TIMEOUT seconds

type ReceiveMessageTimeout

type ReceiveMessageTimeout struct {
	QueueUrl   string
	TimeoutSec int
}

func (ReceiveMessageTimeout) Error

func (err ReceiveMessageTimeout) Error() string

type Subnet

type Subnet struct {
	Id               string // The ID of the Subnet
	AvailabilityZone string // The Availability Zone the subnet is in
}

func GetSubnetsForVpc

func GetSubnetsForVpc(t *testing.T, vpcId string, region string) []Subnet

Get the subnets in the specified VPC

func GetSubnetsForVpcE

func GetSubnetsForVpcE(t *testing.T, vpcId string, region string) ([]Subnet, error)

Get the subnets in the specified VPC

type Vpc

type Vpc struct {
	Id      string   // The ID of the VPC
	Name    string   // The name of the VPC
	Subnets []Subnet // A list of subnets in the VPC
}

func GetDefaultVpc

func GetDefaultVpc(t *testing.T, region string) *Vpc

Fetch information about the default VPC in the given region

func GetDefaultVpcE

func GetDefaultVpcE(t *testing.T, region string) (*Vpc, error)

Fetch information about the default VPC in the given region

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL